# HG changeset patch
# User cl349@xxxxxxxxxxxxxxxxxxxx
# Node ID dd668f7527cb35b4e2c2434720d65ce7e9eeceaa
# Parent 84ab93e1ee05015bcc1c3218fac5b3cfd9fb2ffb
# Parent e02a45b9104380bc7593c54554469bbb6e92e56d
merge?
diff -r 84ab93e1ee05 -r dd668f7527cb .hgignore
--- a/.hgignore Thu Sep 1 10:08:53 2005
+++ b/.hgignore Thu Sep 1 10:16:14 2005
@@ -141,6 +141,9 @@
^tools/vnet/vnet-module/\.tmp_versions/.*$
^tools/vnet/vnet-module/vnet_module\.mod\..*$
^tools/vnetd/vnetd$
+^tools/vtpm/vtpm*
+^tools/vtpm/tpm_emulator-*
+^tools/vtpm_manager/manager/vtpm_managerd
^tools/web-shutdown\.tap$
^tools/x2d2/minixend$
^tools/xcs/xcs$
diff -r 84ab93e1ee05 -r dd668f7527cb Config.mk
--- a/Config.mk Thu Sep 1 10:08:53 2005
+++ b/Config.mk Thu Sep 1 10:16:14 2005
@@ -48,3 +48,4 @@
# Optional components
XENSTAT_XENTOP ?= y
+VTPM_TOOLS ?= n
diff -r 84ab93e1ee05 -r dd668f7527cb Makefile
--- a/Makefile Thu Sep 1 10:08:53 2005
+++ b/Makefile Thu Sep 1 10:16:14 2005
@@ -35,11 +35,11 @@
export pae=y
endif
-.PHONY: all dist install xen tools kernels docs world clean mkpatches
mrproper
+.PHONY: all dist install xen kernels tools docs world clean mkpatches
mrproper
.PHONY: kbuild kdelete kclean
# build and install everything into the standard system directories
-install: install-xen install-tools install-kernels install-docs
+install: install-xen install-kernels install-tools install-docs
build: kernels
$(MAKE) -C xen build
@@ -47,7 +47,7 @@
$(MAKE) -C docs build
# build and install everything into local dist directory
-dist: xen tools kernels docs
+dist: xen kernels tools docs
$(INSTALL_DIR) $(DISTDIR)/check
$(INSTALL_DATA) ./COPYING $(DISTDIR)
$(INSTALL_DATA) ./README $(DISTDIR)
diff -r 84ab93e1ee05 -r dd668f7527cb linux-2.6-xen-sparse/arch/xen/Kconfig
--- a/linux-2.6-xen-sparse/arch/xen/Kconfig Thu Sep 1 10:08:53 2005
+++ b/linux-2.6-xen-sparse/arch/xen/Kconfig Thu Sep 1 10:16:14 2005
@@ -69,6 +69,27 @@
The network-device backend driver allows the kernel to export its
network devices to other guests via a high-performance shared-memory
interface.
+
+config XEN_TPMDEV_FRONTEND
+ bool "TPM-device frontend driver"
+ default n
+ help
+ The TPM-device frontend driver.
+
+config XEN_TPMDEV_BACKEND
+ bool "TPM-device backend driver"
+ default n
+ help
+ The TPM-device backend driver
+
+config XEN_TPMDEV_CLOSE_IF_VTPM_FAILS
+ bool "TPM backend closes upon vTPM failure"
+ depends on XEN_TPMDEV_BACKEND
+ default n
+ help
+ The TPM backend closes the channel if the vTPM in userspace indicates
+ a failure. The corresponding domain's channel will be closed.
+ Say Y if you want this feature.
config XEN_BLKDEV_FRONTEND
bool "Block-device frontend driver"
diff -r 84ab93e1ee05 -r dd668f7527cb
linux-2.6-xen-sparse/arch/xen/Kconfig.drivers
--- a/linux-2.6-xen-sparse/arch/xen/Kconfig.drivers Thu Sep 1 10:08:53 2005
+++ b/linux-2.6-xen-sparse/arch/xen/Kconfig.drivers Thu Sep 1 10:16:14 2005
@@ -49,6 +49,10 @@
endif
if !XEN_PHYSDEV_ACCESS
+source "drivers/char/tpm/Kconfig.domU"
+endif
+
+if !XEN_PHYSDEV_ACCESS
menu "Character devices"
diff -r 84ab93e1ee05 -r dd668f7527cb
linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_32
--- a/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_32 Thu Sep
1 10:08:53 2005
+++ b/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_32 Thu Sep
1 10:16:14 2005
@@ -15,6 +15,8 @@
CONFIG_XEN_BLKDEV_BACKEND=y
# CONFIG_XEN_BLKDEV_TAP_BE is not set
CONFIG_XEN_NETDEV_BACKEND=y
+# CONFIG_XEN_TPMDEV_FRONTEND is not set
+# CONFIG_XEN_TPMDEV_BACKEND is not set
CONFIG_XEN_BLKDEV_FRONTEND=y
CONFIG_XEN_NETDEV_FRONTEND=y
CONFIG_XEN_NETDEV_GRANT_TX=y
diff -r 84ab93e1ee05 -r dd668f7527cb
linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_64
--- a/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_64 Thu Sep
1 10:08:53 2005
+++ b/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_64 Thu Sep
1 10:16:14 2005
@@ -15,6 +15,8 @@
CONFIG_XEN_BLKDEV_BACKEND=y
# CONFIG_XEN_BLKDEV_TAP_BE is not set
CONFIG_XEN_NETDEV_BACKEND=y
+# CONFIG_XEN_TPMDEV_FRONTEND is not set
+# CONFIG_XEN_TPMDEV_BACKEND is not set
CONFIG_XEN_BLKDEV_FRONTEND=y
CONFIG_XEN_NETDEV_FRONTEND=y
CONFIG_XEN_NETDEV_GRANT_TX=y
diff -r 84ab93e1ee05 -r dd668f7527cb
linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_32
--- a/linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_32 Thu Sep
1 10:08:53 2005
+++ b/linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_32 Thu Sep
1 10:16:14 2005
@@ -12,6 +12,8 @@
#
# CONFIG_XEN_PRIVILEGED_GUEST is not set
# CONFIG_XEN_PHYSDEV_ACCESS is not set
+# CONFIG_XEN_TPMDEV_FRONTEND is not set
+# CONFIG_XEN_TPMDEV_BACKEND is not set
CONFIG_XEN_BLKDEV_FRONTEND=y
CONFIG_XEN_NETDEV_FRONTEND=y
CONFIG_XEN_NETDEV_GRANT_TX=y
@@ -336,6 +338,7 @@
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_TCG_TPM is not set
#
# Character devices
diff -r 84ab93e1ee05 -r dd668f7527cb
linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_64
--- a/linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_64 Thu Sep
1 10:08:53 2005
+++ b/linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_64 Thu Sep
1 10:16:14 2005
@@ -12,6 +12,8 @@
#
# CONFIG_XEN_PRIVILEGED_GUEST is not set
# CONFIG_XEN_PHYSDEV_ACCESS is not set
+# CONFIG_XEN_TPMDEV_FRONTEND is not set
+# CONFIG_XEN_TPMDEV_BACKEND is not set
CONFIG_XEN_BLKDEV_FRONTEND=y
CONFIG_XEN_NETDEV_FRONTEND=y
CONFIG_XEN_NETDEV_GRANT_TX=y
@@ -662,6 +664,7 @@
CONFIG_INPUT=m
CONFIG_UNIX98_PTYS=y
# CONFIG_LEGACY_PTYS is not set
+# CONFIG_TCG_TPM is not set
#
# Character devices
diff -r 84ab93e1ee05 -r dd668f7527cb
linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_32
--- a/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_32 Thu Sep
1 10:08:53 2005
+++ b/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_32 Thu Sep
1 10:16:14 2005
@@ -15,6 +15,8 @@
CONFIG_XEN_BLKDEV_BACKEND=y
# CONFIG_XEN_BLKDEV_TAP_BE is not set
CONFIG_XEN_NETDEV_BACKEND=y
+# CONFIG_XEN_TPMDEV_FRONTEND is not set
+# CONFIG_XEN_TPMDEV_BACKEND is not set
CONFIG_XEN_BLKDEV_FRONTEND=y
CONFIG_XEN_NETDEV_FRONTEND=y
CONFIG_XEN_NETDEV_GRANT_TX=y
@@ -1855,9 +1857,7 @@
#
# TPM devices
#
-CONFIG_TCG_TPM=m
-CONFIG_TCG_NSC=m
-CONFIG_TCG_ATMEL=m
+# CONFIG_TCG_TPM is not set
#
# I2C support
diff -r 84ab93e1ee05 -r dd668f7527cb
linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_64
--- a/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_64 Thu Sep
1 10:08:53 2005
+++ b/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_64 Thu Sep
1 10:16:14 2005
@@ -15,6 +15,8 @@
CONFIG_XEN_BLKDEV_BACKEND=y
# CONFIG_XEN_BLKDEV_TAP_BE is not set
CONFIG_XEN_NETDEV_BACKEND=y
+# CONFIG_XEN_TPMDEV_FRONTEND is not set
+# CONFIG_XEN_TPMDEV_BACKEND is not set
CONFIG_XEN_BLKDEV_FRONTEND=y
CONFIG_XEN_NETDEV_FRONTEND=y
CONFIG_XEN_NETDEV_GRANT_TX=y
diff -r 84ab93e1ee05 -r dd668f7527cb linux-2.6-xen-sparse/drivers/xen/Makefile
--- a/linux-2.6-xen-sparse/drivers/xen/Makefile Thu Sep 1 10:08:53 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/Makefile Thu Sep 1 10:16:14 2005
@@ -8,7 +8,9 @@
obj-$(CONFIG_XEN_BLKDEV_BACKEND) += blkback/
obj-$(CONFIG_XEN_NETDEV_BACKEND) += netback/
+obj-$(CONFIG_XEN_TPMDEV_BACKEND) += tpmback/
obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += blkfront/
obj-$(CONFIG_XEN_NETDEV_FRONTEND) += netfront/
obj-$(CONFIG_XEN_BLKDEV_TAP) += blktap/
+obj-$(CONFIG_XEN_TPMDEV_FRONTEND) += tpmfront/
diff -r 84ab93e1ee05 -r dd668f7527cb
linux-2.6-xen-sparse/include/asm-xen/asm-i386/system.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/system.h Thu Sep 1
10:08:53 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/system.h Thu Sep 1
10:16:14 2005
@@ -561,8 +561,14 @@
#define local_irq_disable() __cli()
#define local_irq_enable() __sti()
+/* Don't use smp_processor_id: this is called in debug versions of that fn. */
+#ifdef CONFIG_SMP
#define irqs_disabled() \
- HYPERVISOR_shared_info->vcpu_data[smp_processor_id()].evtchn_upcall_mask
+ HYPERVISOR_shared_info->vcpu_data[__smp_processor_id()].evtchn_upcall_mask
+#else
+#define irqs_disabled() \
+ HYPERVISOR_shared_info->vcpu_data[0].evtchn_upcall_mask
+#endif
/*
* disable hlt during certain critical i/o operations
diff -r 84ab93e1ee05 -r dd668f7527cb
linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/system.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/system.h Thu Sep 1
10:08:53 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/system.h Thu Sep 1
10:16:14 2005
@@ -387,8 +387,14 @@
#define local_irq_disable() __cli()
#define local_irq_enable() __sti()
+/* Don't use smp_processor_id: this is called in debug versions of that fn. */
+#ifdef CONFIG_SMP
#define irqs_disabled() \
- HYPERVISOR_shared_info->vcpu_data[smp_processor_id()].evtchn_upcall_mask
+ HYPERVISOR_shared_info->vcpu_data[__smp_processor_id()].evtchn_upcall_mask
+#else
+#define irqs_disabled() \
+ HYPERVISOR_shared_info->vcpu_data[0].evtchn_upcall_mask
+#endif
/*
* disable hlt during certain critical i/o operations
diff -r 84ab93e1ee05 -r dd668f7527cb tools/Makefile
--- a/tools/Makefile Thu Sep 1 10:08:53 2005
+++ b/tools/Makefile Thu Sep 1 10:16:14 2005
@@ -12,7 +12,13 @@
SUBDIRS += firmware
SUBDIRS += security
SUBDIRS += console
+ifeq ($(VTPM_TOOLS),y)
+SUBDIRS += vtpm_manager
+SUBDIRS += vtpm
+endif
SUBDIRS += xenstat
+
+.PHONY: all install clean check check_clean ioemu eioemuinstall ioemuclean
# These don't cross-compile
ifeq ($(XEN_COMPILE_ARCH),$(XEN_TARGET_ARCH))
diff -r 84ab93e1ee05 -r dd668f7527cb tools/examples/xmexample1
--- a/tools/examples/xmexample1 Thu Sep 1 10:08:53 2005
+++ b/tools/examples/xmexample1 Thu Sep 1 10:16:14 2005
@@ -48,6 +48,20 @@
disk = [ 'phy:hda1,hda1,w' ]
#----------------------------------------------------------------------------
+# Define to which TPM instance the user domain should communicate.
+# The vtpm entry is of the form 'instance=INSTANCE,backend=DOM'
+# where INSTANCE indicates the instance number of the TPM the VM
+# should be talking to and DOM provides the domain where the backend
+# is located.
+# Note that no two virtual machines should try to connect to the same
+# TPM instance. The handling of all TPM instances does require
+# some management effort in so far that VM configration files (and thus
+# a VM) should be associated with a TPM instance throughout the lifetime
+# of the VM / VM configuration file. The instance number must be
+# greater or equal to 1.
+#vtpm = [ 'instance=1,backend=0' ]
+
+#----------------------------------------------------------------------------
# Set the kernel command line for the new domain.
# You only need to define the IP parameters and hostname if the domain's
# IP config doesn't, e.g. in ifcfg-eth0 or via DHCP.
diff -r 84ab93e1ee05 -r dd668f7527cb tools/examples/xmexample2
--- a/tools/examples/xmexample2 Thu Sep 1 10:08:53 2005
+++ b/tools/examples/xmexample2 Thu Sep 1 10:16:14 2005
@@ -84,6 +84,20 @@
'phy:sda6,sda6,r' ]
#----------------------------------------------------------------------------
+# Define to which TPM instance the user domain should communicate.
+# The vtpm entry is of the form 'instance=INSTANCE,backend=DOM'
+# where INSTANCE indicates the instance number of the TPM the VM
+# should be talking to and DOM provides the domain where the backend
+# is located.
+# Note that no two virtual machines should try to connect to the same
+# TPM instance. The handling of all TPM instances does require
+# some management effort in so far that VM configration files (and thus
+# a VM) should be associated with a TPM instance throughout the lifetime
+# of the VM / VM configuration file. The instance number must be
+# greater or equal to 1.
+#vtpm = ['instance=%d,backend=0' % (vmid) ]
+
+#----------------------------------------------------------------------------
# Set the kernel command line for the new domain.
# You only need to define the IP parameters and hostname if the domain's
# IP config doesn't, e.g. in ifcfg-eth0 or via DHCP.
diff -r 84ab93e1ee05 -r dd668f7527cb tools/examples/xmexample3
--- a/tools/examples/xmexample3 Thu Sep 1 10:08:53 2005
+++ b/tools/examples/xmexample3 Thu Sep 1 10:16:14 2005
@@ -80,6 +80,20 @@
disk = [ 'phy:hda%d,hda1,w' % (vmid)]
#----------------------------------------------------------------------------
+# Define to which TPM instance the user domain should communicate.
+# The vtpm entry is of the form 'instance=INSTANCE,backend=DOM'
+# where INSTANCE indicates the instance number of the TPM the VM
+# should be talking to and DOM provides the domain where the backend
+# is located.
+# Note that no two virtual machines should try to connect to the same
+# TPM instance. The handling of all TPM instances does require
+# some management effort in so far that VM configration files (and thus
+# a VM) should be associated with a TPM instance throughout the lifetime
+# of the VM / VM configuration file. The instance number must be
+# greater or equal to 1.
+#vtpm = ['instance=%d,backend=0' % (vmid) ]
+
+#----------------------------------------------------------------------------
# Set the kernel command line for the new domain.
# You only need to define the IP parameters and hostname if the domain's
# IP config doesn't, e.g. in ifcfg-eth0 or via DHCP.
diff -r 84ab93e1ee05 -r dd668f7527cb tools/libxc/xc_private.c
--- a/tools/libxc/xc_private.c Thu Sep 1 10:08:53 2005
+++ b/tools/libxc/xc_private.c Thu Sep 1 10:16:14 2005
@@ -422,3 +422,8 @@
{
return do_dom0_op(xc_handle, op);
}
+
+int xc_version(int xc_handle, int cmd, void *arg)
+{
+ return do_xen_version(xc_handle, cmd, arg);
+}
diff -r 84ab93e1ee05 -r dd668f7527cb tools/libxc/xc_private.h
--- a/tools/libxc/xc_private.h Thu Sep 1 10:08:53 2005
+++ b/tools/libxc/xc_private.h Thu Sep 1 10:16:14 2005
@@ -59,6 +59,17 @@
(unsigned long)hypercall);
}
+static inline int do_xen_version(int xc_handle, int cmd, void *dest)
+{
+ privcmd_hypercall_t hypercall;
+
+ hypercall.op = __HYPERVISOR_xen_version;
+ hypercall.arg[0] = (unsigned long) cmd;
+ hypercall.arg[1] = (unsigned long) dest;
+
+ return do_xen_hypercall(xc_handle, &hypercall);
+}
+
static inline int do_dom0_op(int xc_handle, dom0_op_t *op)
{
int ret = -1;
diff -r 84ab93e1ee05 -r dd668f7527cb tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h Thu Sep 1 10:08:53 2005
+++ b/tools/libxc/xenctrl.h Thu Sep 1 10:16:14 2005
@@ -23,6 +23,7 @@
#include <sys/ptrace.h>
#include <xen/xen.h>
#include <xen/dom0_ops.h>
+#include <xen/version.h>
#include <xen/event_channel.h>
#include <xen/sched_ctl.h>
#include <xen/acm.h>
@@ -497,6 +498,8 @@
/* Execute a privileged dom0 operation. */
int xc_dom0_op(int xc_handle, dom0_op_t *op);
+int xc_version(int xc_handle, int cmd, void *arg);
+
/* Initializes the store (for dom0)
remote_port should be the remote end of a bound interdomain channel between
the store and dom0.
diff -r 84ab93e1ee05 -r dd668f7527cb tools/python/xen/lowlevel/xc/xc.c
--- a/tools/python/xen/lowlevel/xc/xc.c Thu Sep 1 10:08:53 2005
+++ b/tools/python/xen/lowlevel/xc/xc.c Thu Sep 1 10:16:14 2005
@@ -707,6 +707,39 @@
"cpu_khz", info.cpu_khz);
}
+static PyObject *pyxc_xeninfo(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
+{
+ XcObject *xc = (XcObject *)self;
+ xen_extraversion_t xen_extra;
+ xen_compile_info_t xen_cc;
+ xen_changeset_info_t xen_chgset;
+ long xen_version;
+
+ xen_version = xc_version(xc->xc_handle, XENVER_version, NULL);
+
+ if ( xc_version(xc->xc_handle, XENVER_extraversion, &xen_extra) != 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ if ( xc_version(xc->xc_handle, XENVER_compile_info, &xen_cc) != 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ if ( xc_version(xc->xc_handle, XENVER_changeset, &xen_chgset) != 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ return Py_BuildValue("{s:i,s:i,s:s,s:s,s:s,s:s,s:s,s:s}",
+ "xen_major", xen_version >> 16,
+ "xen_minor", (xen_version & 0xffff),
+ "xen_extra", xen_extra,
+ "xen_changeset", xen_chgset,
+ "cc_compiler", xen_cc.compiler,
+ "cc_compile_by", xen_cc.compile_by,
+ "cc_compile_domain", xen_cc.compile_domain,
+ "cc_compile_date", xen_cc.compile_date);
+}
+
+
static PyObject *pyxc_sedf_domain_set(PyObject *self,
PyObject *args,
PyObject *kwds)
@@ -1089,6 +1122,13 @@
"Returns [dict]: information about the hardware"
" [None]: on failure.\n" },
+ { "xeninfo",
+ (PyCFunction)pyxc_xeninfo,
+ METH_VARARGS, "\n"
+ "Get information about the Xen host\n"
+ "Returns [dict]: information about Xen"
+ " [None]: on failure.\n" },
+
{ "shadow_control",
(PyCFunction)pyxc_shadow_control,
METH_VARARGS | METH_KEYWORDS, "\n"
diff -r 84ab93e1ee05 -r dd668f7527cb tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py Thu Sep 1 10:08:53 2005
+++ b/tools/python/xen/xend/XendDomainInfo.py Thu Sep 1 10:16:14 2005
@@ -269,6 +269,7 @@
self.blkif_backend = False
self.netif_backend = False
self.netif_idx = 0
+ self.tpmif_backend = False
#todo: state: running, suspended
self.state = STATE_VM_OK
@@ -458,6 +459,31 @@
return
+ if type == 'vtpm':
+ backdom = domain_exists(sxp.child_value(devconfig, 'backend', '0'))
+
+ devnum = int(sxp.child_value(devconfig, 'instance', '0'))
+ log.error("The domain has a TPM with instance %d." % devnum)
+
+ # create backend db
+ backdb = backdom.db.addChild("/backend/%s/%s/%d" %
+ (type, self.uuid, devnum))
+ # create frontend db
+ db = self.db.addChild("/device/%s/%d" % (type, devnum))
+
+ backdb['frontend'] = db.getPath()
+ backdb['frontend-id'] = "%i" % self.id
+ backdb['instance'] = sxp.child_value(devconfig, 'instance', '0')
+ backdb.saveDB(save=True)
+
+ db['handle'] = "%i" % devnum
+ db['backend'] = backdb.getPath()
+ db['backend-id'] = "%i" % int(sxp.child_value(devconfig,
+ 'backend', '0'))
+ db.saveDB(save=True)
+
+ return
+
ctrl = self.findDeviceController(type)
return ctrl.createDevice(devconfig, recreate=self.recreate,
change=change)
@@ -779,6 +805,11 @@
for dev in typedb.keys():
typedb[dev].delete()
typedb.saveDB(save=True)
+ if type == 'vtpm':
+ typedb = ddb.addChild(type)
+ for dev in typedb.keys():
+ typedb[dev].delete()
+ typedb.saveDB(save=True)
def show(self):
"""Print virtual machine info.
@@ -1018,6 +1049,8 @@
self.netif_backend = True
elif name == 'usbif':
self.usbif_backend = True
+ elif name == 'tpmif':
+ self.tpmif_backend = True
else:
raise VmError('invalid backend type:' + str(name))
@@ -1189,6 +1222,10 @@
controller.addDevControllerClass("vif", netif.NetifController)
add_device_handler("vif", "vif")
+from server import tpmif
+controller.addDevControllerClass("vtpm", tpmif.TPMifController)
+add_device_handler("vtpm", "vtpm")
+
from server import pciif
controller.addDevControllerClass("pci", pciif.PciController)
add_device_handler("pci", "pci")
diff -r 84ab93e1ee05 -r dd668f7527cb tools/python/xen/xend/XendNode.py
--- a/tools/python/xen/xend/XendNode.py Thu Sep 1 10:08:53 2005
+++ b/tools/python/xen/xend/XendNode.py Thu Sep 1 10:16:14 2005
@@ -46,7 +46,7 @@
return self.xc.bvtsched_global_get()
def info(self):
- return self.nodeinfo() + self.physinfo()
+ return self.nodeinfo() + self.physinfo() + self.xeninfo()
def nodeinfo(self):
(sys, host, rel, ver, mch) = os.uname()
@@ -65,7 +65,16 @@
['free_memory', pinfo['free_pages']/256]]
return info
-
+ def xeninfo(self):
+ xinfo = self.xc.xeninfo()
+ return [['xen_major', xinfo['xen_major']],
+ ['xen_minor', xinfo['xen_minor']],
+ ['xen_extra', xinfo['xen_extra']],
+ ['xen_changeset', xinfo['xen_changeset']],
+ ['cc_compiler', xinfo['cc_compiler']],
+ ['cc_compile_by', xinfo['cc_compile_by']],
+ ['cc_compile_domain', xinfo['cc_compile_domain']],
+ ['cc_compile_date', xinfo['cc_compile_date']]]
def instance():
global inst
diff -r 84ab93e1ee05 -r dd668f7527cb tools/python/xen/xend/image.py
--- a/tools/python/xen/xend/image.py Thu Sep 1 10:08:53 2005
+++ b/tools/python/xen/xend/image.py Thu Sep 1 10:16:14 2005
@@ -31,6 +31,9 @@
"""Flag for a net device backend domain."""
SIF_NET_BE_DOMAIN = (1<<5)
+
+"""Flag for a TPM device backend domain."""
+SIF_TPM_BE_DOMAIN = (1<<7)
class ImageHandler:
"""Abstract base class for image handlers.
@@ -194,6 +197,7 @@
self.flags = 0
if self.vm.netif_backend: self.flags |= SIF_NET_BE_DOMAIN
if self.vm.blkif_backend: self.flags |= SIF_BLK_BE_DOMAIN
+ if self.vm.tpmif_backend: self.flags |= SIF_TPM_BE_DOMAIN
if self.vm.recreate or self.vm.restore:
return
@@ -366,6 +370,11 @@
mac = sxp.child_value(vifinfo, 'mac')
ret.append("-macaddr")
ret.append("%s" % mac)
+ if name == 'vtpm':
+ vtpminfo = sxp.child(device, 'vtpm')
+ instance = sxp.child_value(vtpminfo, 'instance')
+ ret.append("-instance")
+ ret.append("%s" % instance)
# Handle graphics library related options
vnc = sxp.child_value(self.vm.config, 'vnc')
diff -r 84ab93e1ee05 -r dd668f7527cb tools/python/xen/xm/create.py
--- a/tools/python/xen/xm/create.py Thu Sep 1 10:08:53 2005
+++ b/tools/python/xen/xm/create.py Thu Sep 1 10:16:14 2005
@@ -176,6 +176,12 @@
fn=set_bool, default=0,
use="Make the domain a network interface backend.")
+gopts.var('tpmif', val='frontend=DOM',
+ fn=append_value, default=[],
+ use="""Make the domain a TPM interface backend. If frontend is given,
+ the frontend in that domain is connected to this backend (not
+ completely implemented, yet)""")
+
gopts.var('disk', val='phy:DEV,VDEV,MODE[,DOM]',
fn=append_value, default=[],
use="""Add a disk device to a domain. The physical device is DEV,
@@ -213,6 +219,12 @@
where D is the domain id and N is the interface id.
This option may be repeated to add more than one vif.
Specifying vifs will increase the number of interfaces as needed.""")
+
+gopts.var('vtpm', val="instance=INSTANCE,backend=DOM",
+ fn=append_value, default=[],
+ use="""Add a tpm interface. On the backend side us the the given
+ instance as virtual TPM instance. Use the backend in the given
+ domain.""")
gopts.var('nics', val="NUM",
fn=set_int, default=1,
@@ -373,6 +385,46 @@
for path in vals.usb:
config_usb = ['usb', ['path', path]]
config_devs.append(['device', config_usb])
+
+def configure_vtpm(opts, config_devs, vals):
+ """Create the config for virtual TPM interfaces.
+ """
+ vtpm = vals.vtpm
+ vtpm_n = 1
+ for idx in range(0, vtpm_n):
+ if idx < len(vtpm):
+ d = vtpm[idx]
+ instance = d.get('instance')
+ if instance == "VTPMD":
+ instance = "0"
+ else:
+ try:
+ if int(instance) == 0:
+ opts.err('VM config error: vTPM instance must not be
0.')
+ except ValueError:
+ opts.err('Vm config error: could not parse instance
number.')
+ backend = d.get('backend')
+ config_vtpm = ['vtpm']
+ if instance:
+ config_vtpm.append(['instance', instance])
+ if backend:
+ config_vtpm.append(['backend', backend])
+ config_devs.append(['device', config_vtpm])
+
+def configure_tpmif(opts, config_devs, vals):
+ """Create the config for virtual TPM interfaces.
+ """
+ tpmif = vals.tpmif
+ tpmif_n = 1
+ for idx in range(0, tpmif_n):
+ if idx < len(tpmif):
+ d = tpmif[idx]
+ frontend = d.get('frontend')
+ config_tpmif = ['tpmif']
+ if frontend:
+ config_tpmif.append(['frontend', frontend])
+ config_devs.append(['device', config_tpmif])
+
def randomMAC():
"""Generate a random MAC address.
@@ -484,6 +536,8 @@
config.append(['backend', ['blkif']])
if vals.netif:
config.append(['backend', ['netif']])
+ if vals.tpmif:
+ config.append(['backend', ['tpmif']])
if vals.restart:
config.append(['restart', vals.restart])
@@ -496,6 +550,7 @@
configure_pci(opts, config_devs, vals)
configure_vifs(opts, config_devs, vals)
configure_usb(opts, config_devs, vals)
+ configure_vtpm(opts, config_devs, vals)
configure_vmx(opts, config_devs, vals)
config += config_devs
@@ -543,6 +598,38 @@
d[k] = v
vifs.append(d)
vals.vif = vifs
+
+def preprocess_vtpm(opts, vals):
+ if not vals.vtpm: return
+ vtpms = []
+ for vtpm in vals.vtpm:
+ d = {}
+ a = vtpm.split(',')
+ for b in a:
+ (k, v) = b.strip().split('=', 1)
+ k = k.strip()
+ v = v.strip()
+ if k not in ['backend', 'instance']:
+ opts.err('Invalid vtpm specifier: ' + vtpm)
+ d[k] = v
+ vtpms.append(d)
+ vals.vtpm = vtpms
+
+def preprocess_tpmif(opts, vals):
+ if not vals.tpmif: return
+ tpmifs = []
+ for tpmif in vals.tpmif:
+ d = {}
+ a = tpmif.split(',')
+ for b in a:
+ (k, v) = b.strip().split('=', 1)
+ k = k.strip()
+ v = v.strip()
+ if k not in ['frontend']:
+ opts.err('Invalid tpmif specifier: ' + vtpm)
+ d[k] = v
+ tpmifs.append(d)
+ vals.tpmif = tpmifs
def preprocess_ip(opts, vals):
if vals.ip or vals.dhcp != 'off':
@@ -632,6 +719,8 @@
preprocess_ip(opts, vals)
preprocess_nfs(opts, vals)
preprocess_vnc(opts, vals)
+ preprocess_vtpm(opts, vals)
+ preprocess_tpmif(opts, vals)
def make_domain(opts, config):
"""Create, build and start a domain.
diff -r 84ab93e1ee05 -r dd668f7527cb xen/arch/x86/cdb.c
--- a/xen/arch/x86/cdb.c Thu Sep 1 10:08:53 2005
+++ b/xen/arch/x86/cdb.c Thu Sep 1 10:16:14 2005
@@ -21,7 +21,7 @@
debugger. so avoid it. */
#define dbg_printk(...)
-static unsigned char opt_cdb[30] = "none";
+static char opt_cdb[30] = "none";
string_param("cdb", opt_cdb);
struct xendbg_context {
diff -r 84ab93e1ee05 -r dd668f7527cb xen/arch/x86/domain_build.c
--- a/xen/arch/x86/domain_build.c Thu Sep 1 10:08:53 2005
+++ b/xen/arch/x86/domain_build.c Thu Sep 1 10:16:14 2005
@@ -20,6 +20,7 @@
#include <asm/processor.h>
#include <asm/desc.h>
#include <asm/i387.h>
+#include <asm/physdev.h>
#include <asm/shadow.h>
static long dom0_nrpages;
@@ -707,6 +708,18 @@
printk("dom0: shadow setup done\n");
}
+ /*
+ * Modify I/O port access permissions.
+ */
+ /* Master Interrupt Controller (PIC). */
+ physdev_modify_ioport_access_range(dom0, 0, 0x20, 2);
+ /* Slave Interrupt Controller (PIC). */
+ physdev_modify_ioport_access_range(dom0, 0, 0xA0, 2);
+ /* Interval Timer (PIT). */
+ physdev_modify_ioport_access_range(dom0, 0, 0x40, 4);
+ /* PIT Channel 2 / PC Speaker Control. */
+ physdev_modify_ioport_access_range(dom0, 0, 0x61, 1);
+
return 0;
}
diff -r 84ab93e1ee05 -r dd668f7527cb xen/common/kernel.c
--- a/xen/common/kernel.c Thu Sep 1 10:08:53 2005
+++ b/xen/common/kernel.c Thu Sep 1 10:16:14 2005
@@ -110,6 +110,27 @@
return -EFAULT;
return 0;
}
+
+ case XENVER_capabilities:
+ {
+ struct xen_capabilities_info info;
+
+ /* FIXME */
+ info.arch = 0;
+ info.pae = 0;
+ if ( copy_to_user(arg, &info, sizeof(info)) )
+ return -EFAULT;
+ return 0;
+ }
+
+ case XENVER_changeset:
+ {
+ xen_changeset_info_t chgset;
+ safe_strcpy(chgset, XEN_CHANGESET);
+ if ( copy_to_user(arg, chgset, sizeof(chgset)) )
+ return -EFAULT;
+ return 0;
+ }
}
return -ENOSYS;
diff -r 84ab93e1ee05 -r dd668f7527cb xen/include/asm-x86/asm_defns.h
--- a/xen/include/asm-x86/asm_defns.h Thu Sep 1 10:08:53 2005
+++ b/xen/include/asm-x86/asm_defns.h Thu Sep 1 10:16:14 2005
@@ -6,11 +6,6 @@
#include <asm/asm-offsets.h>
#include <asm/processor.h>
-#ifndef STR
-#define __STR(x) #x
-#define STR(x) __STR(x)
-#endif
-
#ifdef __x86_64__
#include <asm/x86_64/asm_defns.h>
#else
diff -r 84ab93e1ee05 -r dd668f7527cb xen/include/asm-x86/bitops.h
--- a/xen/include/asm-x86/bitops.h Thu Sep 1 10:08:53 2005
+++ b/xen/include/asm-x86/bitops.h Thu Sep 1 10:16:14 2005
@@ -6,11 +6,6 @@
*/
#include <xen/config.h>
-
-#ifndef STR
-#define __STR(x) #x
-#define STR(x) __STR(x)
-#endif
/*
* These have to be done with inline assembly: that way the bit-setting
diff -r 84ab93e1ee05 -r dd668f7527cb xen/include/asm-x86/shadow_64.h
--- a/xen/include/asm-x86/shadow_64.h Thu Sep 1 10:08:53 2005
+++ b/xen/include/asm-x86/shadow_64.h Thu Sep 1 10:16:14 2005
@@ -450,7 +450,9 @@
/*
* If it's not external mode, then mfn should be machine physical.
*/
- mfn = __gpfn_to_mfn(d, (entry_get_value(gle) >> PAGE_SHIFT));
+ mfn = __gpfn_to_mfn(d, (entry_get_paddr(gle) >> PAGE_SHIFT));
+ if (mfn == -1)
+ return 1;
lva = (pgentry_64_t *) phys_to_virt(
mfn << PAGE_SHIFT);
diff -r 84ab93e1ee05 -r dd668f7527cb xen/include/asm-x86/x86_32/asm_defns.h
--- a/xen/include/asm-x86/x86_32/asm_defns.h Thu Sep 1 10:08:53 2005
+++ b/xen/include/asm-x86/x86_32/asm_defns.h Thu Sep 1 10:16:14 2005
@@ -1,45 +1,5 @@
#ifndef __X86_32_ASM_DEFNS_H__
#define __X86_32_ASM_DEFNS_H__
-
-/* Maybe auto-generate the following two cases (quoted vs. unquoted). */
-#ifndef __ASSEMBLY__
-
-#define __SAVE_ALL_PRE \
- "cld;" \
- "pushl %eax;" \
- "pushl %ebp;" \
- "pushl %edi;" \
- "pushl %esi;" \
- "pushl %edx;" \
- "pushl %ecx;" \
- "pushl %ebx;" \
- "testl $"STR(X86_EFLAGS_VM)","STR(UREGS_eflags)"(%esp);" \
- "jz 2f;" \
- "call setup_vm86_frame;" \
- "jmp 3f;" \
- "2:testb $3,"STR(UREGS_cs)"(%esp);" \
- "jz 1f;" \
- "mov %ds,"STR(UREGS_ds)"(%esp);" \
- "mov %es,"STR(UREGS_es)"(%esp);" \
- "mov %fs,"STR(UREGS_fs)"(%esp);" \
- "mov %gs,"STR(UREGS_gs)"(%esp);" \
- "3:"
-
-#define SAVE_ALL_NOSEGREGS(_reg) \
- __SAVE_ALL_PRE \
- "1:"
-
-#define SET_XEN_SEGMENTS(_reg) \
- "movl $("STR(__HYPERVISOR_DS)"),%e"STR(_reg)"x;" \
- "mov %e"STR(_reg)"x,%ds;" \
- "mov %e"STR(_reg)"x,%es;"
-
-#define SAVE_ALL(_reg) \
- __SAVE_ALL_PRE \
- SET_XEN_SEGMENTS(_reg) \
- "1:"
-
-#else
#define __SAVE_ALL_PRE \
cld; \
@@ -50,7 +10,7 @@
pushl %edx; \
pushl %ecx; \
pushl %ebx; \
- testl $X86_EFLAGS_VM,UREGS_eflags(%esp); \
+ testl $(X86_EFLAGS_VM),UREGS_eflags(%esp); \
jz 2f; \
call setup_vm86_frame; \
jmp 3f; \
@@ -83,8 +43,6 @@
#define PERFC_INCR(_name,_idx)
#endif
-#endif
-
#define BUILD_SMP_INTERRUPT(x,v) XBUILD_SMP_INTERRUPT(x,v)
#define XBUILD_SMP_INTERRUPT(x,v) \
asmlinkage void x(void); \
@@ -92,7 +50,7 @@
"\n"__ALIGN_STR"\n" \
STR(x) ":\n\t" \
"pushl $"#v"<<16\n\t" \
- SAVE_ALL(a) \
+ STR(SAVE_ALL(a)) \
"call "STR(smp_##x)"\n\t" \
"jmp ret_from_intr\n");
@@ -103,7 +61,7 @@
"\n"__ALIGN_STR"\n" \
STR(x) ":\n\t" \
"pushl $"#v"<<16\n\t" \
- SAVE_ALL(a) \
+ STR(SAVE_ALL(a)) \
"movl %esp,%eax\n\t" \
"pushl %eax\n\t" \
"call "STR(smp_##x)"\n\t" \
@@ -114,7 +72,7 @@
__asm__( \
"\n" __ALIGN_STR"\n" \
"common_interrupt:\n\t" \
- SAVE_ALL(a) \
+ STR(SAVE_ALL(a)) \
"movl %esp,%eax\n\t" \
"pushl %eax\n\t" \
"call " STR(do_IRQ) "\n\t" \
diff -r 84ab93e1ee05 -r dd668f7527cb xen/include/asm-x86/x86_64/asm_defns.h
--- a/xen/include/asm-x86/x86_64/asm_defns.h Thu Sep 1 10:08:53 2005
+++ b/xen/include/asm-x86/x86_64/asm_defns.h Thu Sep 1 10:16:14 2005
@@ -1,49 +1,5 @@
#ifndef __X86_64_ASM_DEFNS_H__
#define __X86_64_ASM_DEFNS_H__
-
-/* Maybe auto-generate the following two cases (quoted vs. unquoted). */
-#ifndef __ASSEMBLY__
-
-#define SAVE_ALL \
- "cld;" \
- "pushq %rdi;" \
- "pushq %rsi;" \
- "pushq %rdx;" \
- "pushq %rcx;" \
- "pushq %rax;" \
- "pushq %r8;" \
- "pushq %r9;" \
- "pushq %r10;" \
- "pushq %r11;" \
- "pushq %rbx;" \
- "pushq %rbp;" \
- "pushq %r12;" \
- "pushq %r13;" \
- "pushq %r14;" \
- "pushq %r15;"
-
-#define RESTORE_ALL \
- "popq %r15;" \
- "popq %r14;" \
- "popq %r13;" \
- "popq %r12;" \
- "popq %rbp;" \
- "popq %rbx;" \
- "popq %r11;" \
- "popq %r10;" \
- "popq %r9;" \
- "popq %r8;" \
- "popq %rax;" \
- "popq %rcx;" \
- "popq %rdx;" \
- "popq %rsi;" \
- "popq %rdi;"
-
-/* Work around AMD erratum #88 */
-#define safe_swapgs \
- "mfence; swapgs;"
-
-#else
#define SAVE_ALL \
cld; \
@@ -90,7 +46,9 @@
#define PERFC_INCR(_name,_idx)
#endif
-#endif
+/* Work around AMD erratum #88 */
+#define safe_swapgs \
+ "mfence; swapgs;"
#define BUILD_SMP_INTERRUPT(x,v) XBUILD_SMP_INTERRUPT(x,v)
#define XBUILD_SMP_INTERRUPT(x,v) \
@@ -100,7 +58,7 @@
STR(x) ":\n\t" \
"pushq $0\n\t" \
"movl $"#v",4(%rsp)\n\t" \
- SAVE_ALL \
+ STR(SAVE_ALL) \
"callq "STR(smp_##x)"\n\t" \
"jmp ret_from_intr\n");
@@ -112,7 +70,7 @@
STR(x) ":\n\t" \
"pushq $0\n\t" \
"movl $"#v",4(%rsp)\n\t" \
- SAVE_ALL \
+ STR(SAVE_ALL) \
"movq %rsp,%rdi\n\t" \
"callq "STR(smp_##x)"\n\t" \
"jmp ret_from_intr\n");
@@ -121,7 +79,7 @@
__asm__( \
"\n" __ALIGN_STR"\n" \
"common_interrupt:\n\t" \
- SAVE_ALL \
+ STR(SAVE_ALL) \
"movq %rsp,%rdi\n\t" \
"callq " STR(do_IRQ) "\n\t" \
"jmp ret_from_intr\n");
diff -r 84ab93e1ee05 -r dd668f7527cb xen/include/public/version.h
--- a/xen/include/public/version.h Thu Sep 1 10:08:53 2005
+++ b/xen/include/public/version.h Thu Sep 1 10:16:14 2005
@@ -28,4 +28,13 @@
char compile_date[32];
} xen_compile_info_t;
+#define XENVER_capabilities 3
+typedef struct xen_capabilities_info {
+ int pae;
+ int arch;
+} xen_capabilities_info_t;
+
+#define XENVER_changeset 4
+typedef char xen_changeset_info_t[64];
+
#endif /* __XEN_PUBLIC_VERSION_H__ */
diff -r 84ab93e1ee05 -r dd668f7527cb xen/include/public/xen.h
--- a/xen/include/public/xen.h Thu Sep 1 10:08:53 2005
+++ b/xen/include/public/xen.h Thu Sep 1 10:16:14 2005
@@ -455,6 +455,7 @@
#define SIF_BLK_BE_DOMAIN (1<<4) /* Is this a block backend domain? */
#define SIF_NET_BE_DOMAIN (1<<5) /* Is this a net backend domain? */
#define SIF_USB_BE_DOMAIN (1<<6) /* Is this a usb backend domain? */
+#define SIF_TPM_BE_DOMAIN (1<<7) /* Is this a TPM backend domain? */
/* For use in guest OSes. */
extern shared_info_t *HYPERVISOR_shared_info;
diff -r 84ab93e1ee05 -r dd668f7527cb xen/include/xen/config.h
--- a/xen/include/xen/config.h Thu Sep 1 10:08:53 2005
+++ b/xen/include/xen/config.h Thu Sep 1 10:16:14 2005
@@ -40,4 +40,7 @@
#include <xen/compiler.h>
#endif
+#define __STR(...) #__VA_ARGS__
+#define STR(...) __STR(__VA_ARGS__)
+
#endif /* __XEN_CONFIG_H__ */
diff -r 84ab93e1ee05 -r dd668f7527cb MSG
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/MSG Thu Sep 1 10:16:14 2005
@@ -0,0 +1,7 @@
+TPM FE/BE code using xenbus (some control message stuff still there; to
+be removed soon).
+
+Signed-off-by: Stefan Berger <stefanb@xxxxxxxxxx>
+Signed-off-by: Kylene Hall <kjhall@xxxxxxxxxx>
+Signed-off-by: Mahadevan Gomathisankaran <gmdev@xxxxxxxxxxx>
+Signed-off-by: Steven Hand <steven@xxxxxxxxxxxxx>
diff -r 84ab93e1ee05 -r dd668f7527cb docs/misc/vtpm.txt
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/docs/misc/vtpm.txt Thu Sep 1 10:16:14 2005
@@ -0,0 +1,122 @@
+Copyright: IBM Corporation (C), Intel Corporation
+17 August 2005
+Authors: Stefan Berger <stefanb@xxxxxxxxxx> (IBM),
+ Employees of Intel Corp
+
+This document gives a short introduction to the virtual TPM support
+in XEN and goes as far as connecting a user domain to a virtual TPM
+instance and doing a short test to verify success. It is assumed
+that the user is fairly familiar with compiling and installing XEN
+and Linux on a machine.
+
+Production Prerequisites: An x86-based machine machine with an ATMEL or
+National Semiconductor (NSC) TPM on the motherboard.
+Development Prerequisites: An emulator for TESTING ONLY is provided
+
+
+Compiling XEN tree:
+-------------------
+
+Compile the XEN tree as usual.
+
+make uninstall; make mrproper; make install
+
+After compiling the tree, verify that in the linux-2.6.XX-xen0/.config
+file at least the following entries are set as below (they should be set
+by default):
+
+CONFIG_XEN_TPMDEV_BACKEND=y
+CONFIG_XEN_TPMDEV_GRANT=y
+
+CONFIG_TCG_TPM=m
+CONFIG_TCG_NSC=m
+CONFIG_TCG_ATMEL=m
+
+
+Verify that in the linux-2.6.XX-xenU/.config file at least the
+Following entries are set as below (they should be set by default):
+
+CONFIG_XEN_TPMDEV_FRONTEND=y
+CONFIG_XEN_TPMDEV_GRANT=y
+
+CONFIG_TCG_TPM=y
+CONFIG_TCG_XEN=y
+
+
+Reboot the machine with the created XEN-0 kernel.
+
+Note: If you do not want any TPM-related code compiled into your
+kernel or built as module then comment all the above lines like
+this example:
+# CONFIG_TCG_TPM is not set
+
+
+Modifying VM Configuration files:
+---------------------------------
+
+VM configuration files need to be adapted to make a TPM instance
+available to a user domain. The following VM configuration file is
+an example of how a user domain can be configured to have a TPM
+available. It works similar to making a network interface
+available to a domain.
+
+kernel = "/boot/vmlinuz-2.6.12-xenU"
+ramdisk = "/xen/initrd_domU/U1_ramdisk.img"
+memory = 32
+name = "TPMUserDomain0"
+vtpm = ['instance=1,backend=0']
+root = "/dev/ram0 cosole=tty ro"
+vif = ['backend=0']
+
+In the above configuration file the line 'vtpm = ...' provides
+information about the domain where the virtual TPM is running and
+where the TPM backend has been compiled into - this has to be
+domain 0 at the moment - and which TPM instance the user domain
+is supposed to talk to. Note that each running VM must use a
+different instance and that using instance 0 is NOT allowed.
+
+Note: If you do not want TPM functionality for your user domain simply
+leave out the 'vtpm' line in the configuration file.
+
+
+Running the TPM:
+----------------
+
+To run the vTPM, dev device /dev/vtpm must be available.
+Verify that 'ls -l /dev/vtpm' shows the following output:
+
+crw------- 1 root root 10, 225 Aug 11 06:58 /dev/vtpm
+
+If it is not available, run the following command as 'root'.
+mknod /dev/vtpm c 10 225
+
+Make sure that the vTPM is running in domain 0. To do this run the
+following
+
+/usr/bin/vtpm_managerd
+
+Start a user domain using the 'xm create' command. Once you are in the
+shell of the user domain, you should be able to do the following:
+
+> cd /sys/devices/vtpm
+> ls
+cancel caps pcrs pubek
+> cat pcrs
+PCR-00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+PCR-01: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+PCR-02: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+PCR-03: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+PCR-04: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+PCR-05: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+PCR-06: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+PCR-07: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+PCR-08: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[...]
+
+At this point the user domain has been sucessfully connected to its
+virtual TPM instance.
+
+For further information please read the documentation in
+tools/vtpm_manager/README and tools/vtpm/README
+
+Stefan Berger and Employees of the Intel Corp
diff -r 84ab93e1ee05 -r dd668f7527cb
linux-2.6-xen-sparse/drivers/char/tpm/Kconfig.domU
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/Kconfig.domU Thu Sep 1
10:16:14 2005
@@ -0,0 +1,30 @@
+#
+# TPM device configuration
+#
+
+menu "TPM devices"
+
+config TCG_TPM
+ tristate "TPM Support for XEN"
+ depends on ARCH_XEN && !XEN_PHYSDEV_ACCESS
+ ---help---
+ If you want to make TPM security available in your system,
+ say Yes and it will be accessible from within a user domain. For
+ more information see <http://www.trustedcomputinggroup.org>.
+ An implementation of the Trusted Software Stack (TSS), the
+ userspace enablement piece of the specification, can be
+ obtained at: <http://sourceforge.net/projects/trousers>. To
+ compile this driver as a module, choose M here; the module
+ will be called tpm. If unsure, say N.
+
+config TCG_XEN
+ tristate "XEN TPM Interface"
+ depends on TCG_TPM && ARCH_XEN
+ ---help---
+ If you want to make TPM support available to a Xen
+ user domain, say Yes and it will
+ be accessible from within Linux. To compile this driver
+ as a module, choose M here; the module will be called
+ tpm_xen.
+
+endmenu
diff -r 84ab93e1ee05 -r dd668f7527cb
linux-2.6-xen-sparse/drivers/char/tpm/Makefile
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/Makefile Thu Sep 1 10:16:14 2005
@@ -0,0 +1,12 @@
+#
+# Makefile for the kernel tpm device drivers.
+#
+ifeq ($(CONFIG_XEN_PHYSDEV_ACCESS),y)
+obj-$(CONFIG_TCG_TPM) += tpm.o
+obj-$(CONFIG_TCG_NSC) += tpm_nsc.o
+obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o
+obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o
+else
+obj-$(CONFIG_TCG_TPM) += tpm_nopci.o
+obj-$(CONFIG_TCG_XEN) += tpm_xen.o
+endif
diff -r 84ab93e1ee05 -r dd668f7527cb linux-2.6-xen-sparse/drivers/char/tpm/tpm.c
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm.c Thu Sep 1 10:16:14 2005
@@ -0,0 +1,627 @@
+/*
+ * Copyright (C) 2004 IBM Corporation
+ *
+ * Authors:
+ * Leendert van Doorn <leendert@xxxxxxxxxxxxxx>
+ * Dave Safford <safford@xxxxxxxxxxxxxx>
+ * Reiner Sailer <sailer@xxxxxxxxxxxxxx>
+ * Kylene Hall <kjhall@xxxxxxxxxx>
+ *
+ * Maintained by: <tpmdd_devel@xxxxxxxxxxxxxxxxxxxxx>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ * Note, the TPM chip is not interrupt driven (only polling)
+ * and can have very long timeouts (minutes!). Hence the unusual
+ * calls to schedule_timeout.
+ *
+ */
+
+#include <linux/sched.h>
+#include <linux/poll.h>
+#include <linux/spinlock.h>
+#include "tpm.h"
+
+#define TPM_MINOR 224 /* officially assigned
*/
+
+#define TPM_BUFSIZE 2048
+
+static LIST_HEAD(tpm_chip_list);
+static DEFINE_SPINLOCK(driver_lock);
+static int dev_mask[32];
+
+static void user_reader_timeout(unsigned long ptr)
+{
+ struct tpm_chip *chip = (struct tpm_chip *) ptr;
+
+ down(&chip->buffer_mutex);
+ atomic_set(&chip->data_pending, 0);
+ memset(chip->data_buffer, 0, TPM_BUFSIZE);
+ up(&chip->buffer_mutex);
+}
+
+void tpm_time_expired(unsigned long ptr)
+{
+ int *exp = (int *) ptr;
+ *exp = 1;
+}
+
+EXPORT_SYMBOL_GPL(tpm_time_expired);
+
+/*
+ * Internal kernel interface to transmit TPM commands
+ */
+static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
+ size_t bufsiz)
+{
+ ssize_t len;
+ u32 count;
+ __be32 *native_size;
+
+ native_size = (__force __be32 *) (buf + 2);
+ count = be32_to_cpu(*native_size);
+
+ if (count == 0)
+ return -ENODATA;
+ if (count > bufsiz) {
+ dev_err(&chip->pci_dev->dev,
+ "invalid count value %x %zx \n", count, bufsiz);
+ return -E2BIG;
+ }
+
+ down(&chip->tpm_mutex);
+
+ if ((len = chip->vendor->send(chip, (u8 *) buf, count)) < 0) {
+ dev_err(&chip->pci_dev->dev,
+ "tpm_transmit: tpm_send: error %zd\n", len);
+ return len;
+ }
+
+ down(&chip->timer_manipulation_mutex);
+ chip->time_expired = 0;
+ init_timer(&chip->device_timer);
+ chip->device_timer.function = tpm_time_expired;
+ chip->device_timer.expires = jiffies + 2 * 60 * HZ;
+ chip->device_timer.data = (unsigned long) &chip->time_expired;
+ add_timer(&chip->device_timer);
+ up(&chip->timer_manipulation_mutex);
+
+ do {
+ u8 status = inb(chip->vendor->base + 1);
+ if ((status & chip->vendor->req_complete_mask) ==
+ chip->vendor->req_complete_val) {
+ down(&chip->timer_manipulation_mutex);
+ del_singleshot_timer_sync(&chip->device_timer);
+ up(&chip->timer_manipulation_mutex);
+ goto out_recv;
+ }
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(TPM_TIMEOUT);
+ rmb();
+ } while (!chip->time_expired);
+
+
+ chip->vendor->cancel(chip);
+ dev_err(&chip->pci_dev->dev, "Time expired\n");
+ up(&chip->tpm_mutex);
+ return -EIO;
+
+out_recv:
+ len = chip->vendor->recv(chip, (u8 *) buf, bufsiz);
+ if (len < 0)
+ dev_err(&chip->pci_dev->dev,
+ "tpm_transmit: tpm_recv: error %zd\n", len);
+ up(&chip->tpm_mutex);
+ return len;
+}
+
+#define TPM_DIGEST_SIZE 20
+#define CAP_PCR_RESULT_SIZE 18
+static u8 cap_pcr[] = {
+ 0, 193, /* TPM_TAG_RQU_COMMAND */
+ 0, 0, 0, 22, /* length */
+ 0, 0, 0, 101, /* TPM_ORD_GetCapability */
+ 0, 0, 0, 5,
+ 0, 0, 0, 4,
+ 0, 0, 1, 1
+};
+
+#define READ_PCR_RESULT_SIZE 30
+static u8 pcrread[] = {
+ 0, 193, /* TPM_TAG_RQU_COMMAND */
+ 0, 0, 0, 14, /* length */
+ 0, 0, 0, 21, /* TPM_ORD_PcrRead */
+ 0, 0, 0, 0 /* PCR index */
+};
+
+static ssize_t show_pcrs(struct device *dev, char *buf)
+{
+ u8 data[READ_PCR_RESULT_SIZE];
+ ssize_t len;
+ int i, j, index, num_pcrs;
+ char *str = buf;
+
+ struct tpm_chip *chip =
+ pci_get_drvdata(container_of(dev, struct pci_dev, dev));
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, cap_pcr, sizeof(cap_pcr));
+ if ((len = tpm_transmit(chip, data, sizeof(data)))
+ < CAP_PCR_RESULT_SIZE)
+ return len;
+
+ num_pcrs = be32_to_cpu(*((__force __be32 *) (data + 14)));
+
+ for (i = 0; i < num_pcrs; i++) {
+ memcpy(data, pcrread, sizeof(pcrread));
+ index = cpu_to_be32(i);
+ memcpy(data + 10, &index, 4);
+ if ((len = tpm_transmit(chip, data, sizeof(data)))
+ < READ_PCR_RESULT_SIZE)
+ return len;
+ str += sprintf(str, "PCR-%02d: ", i);
+ for (j = 0; j < TPM_DIGEST_SIZE; j++)
+ str += sprintf(str, "%02X ", *(data + 10 + j));
+ str += sprintf(str, "\n");
+ }
+ return str - buf;
+}
+
+static DEVICE_ATTR(pcrs, S_IRUGO, show_pcrs, NULL);
+
+#define READ_PUBEK_RESULT_SIZE 314
+static u8 readpubek[] = {
+ 0, 193, /* TPM_TAG_RQU_COMMAND */
+ 0, 0, 0, 30, /* length */
+ 0, 0, 0, 124, /* TPM_ORD_ReadPubek */
+};
+
+static ssize_t show_pubek(struct device *dev, char *buf)
+{
+ u8 data[READ_PUBEK_RESULT_SIZE];
+ ssize_t len;
+ __be32 *native_val;
+ int i;
+ char *str = buf;
+
+ struct tpm_chip *chip =
+ pci_get_drvdata(container_of(dev, struct pci_dev, dev));
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, readpubek, sizeof(readpubek));
+ memset(data + sizeof(readpubek), 0, 20); /* zero nonce */
+
+ if ((len = tpm_transmit(chip, data, sizeof(data))) <
+ READ_PUBEK_RESULT_SIZE)
+ return len;
+
+ /*
+ ignore header 10 bytes
+ algorithm 32 bits (1 == RSA )
+ encscheme 16 bits
+ sigscheme 16 bits
+ parameters (RSA 12->bytes: keybit, #primes, expbit)
+ keylenbytes 32 bits
+ 256 byte modulus
+ ignore checksum 20 bytes
+ */
+
+ native_val = (__force __be32 *) (data + 34);
+
+ str +=
+ sprintf(str,
+ "Algorithm: %02X %02X %02X %02X\nEncscheme: %02X %02X\n"
+ "Sigscheme: %02X %02X\nParameters: %02X %02X %02X %02X"
+ " %02X %02X %02X %02X %02X %02X %02X %02X\n"
+ "Modulus length: %d\nModulus: \n",
+ data[10], data[11], data[12], data[13], data[14],
+ data[15], data[16], data[17], data[22], data[23],
+ data[24], data[25], data[26], data[27], data[28],
+ data[29], data[30], data[31], data[32], data[33],
+ be32_to_cpu(*native_val)
+ );
+
+ for (i = 0; i < 256; i++) {
+ str += sprintf(str, "%02X ", data[i + 39]);
+ if ((i + 1) % 16 == 0)
+ str += sprintf(str, "\n");
+ }
+ return str - buf;
+}
+
+static DEVICE_ATTR(pubek, S_IRUGO, show_pubek, NULL);
+
+#define CAP_VER_RESULT_SIZE 18
+static u8 cap_version[] = {
+ 0, 193, /* TPM_TAG_RQU_COMMAND */
+ 0, 0, 0, 18, /* length */
+ 0, 0, 0, 101, /* TPM_ORD_GetCapability */
+ 0, 0, 0, 6,
+ 0, 0, 0, 0
+};
+
+#define CAP_MANUFACTURER_RESULT_SIZE 18
+static u8 cap_manufacturer[] = {
+ 0, 193, /* TPM_TAG_RQU_COMMAND */
+ 0, 0, 0, 22, /* length */
+ 0, 0, 0, 101, /* TPM_ORD_GetCapability */
+ 0, 0, 0, 5,
+ 0, 0, 0, 4,
+ 0, 0, 1, 3
+};
+
+static ssize_t show_caps(struct device *dev, char *buf)
+{
+ u8 data[READ_PUBEK_RESULT_SIZE];
+ ssize_t len;
+ char *str = buf;
+
+ struct tpm_chip *chip =
+ pci_get_drvdata(container_of(dev, struct pci_dev, dev));
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, cap_manufacturer, sizeof(cap_manufacturer));
+
+ if ((len = tpm_transmit(chip, data, sizeof(data))) <
+ CAP_MANUFACTURER_RESULT_SIZE)
+ return len;
+
+ str += sprintf(str, "Manufacturer: 0x%x\n",
+ be32_to_cpu(*(data + 14)));
+
+ memcpy(data, cap_version, sizeof(cap_version));
+
+ if ((len = tpm_transmit(chip, data, sizeof(data))) <
+ CAP_VER_RESULT_SIZE)
+ return len;
+
+ str +=
+ sprintf(str, "TCG version: %d.%d\nFirmware version: %d.%d\n",
+ (int) data[14], (int) data[15], (int) data[16],
+ (int) data[17]);
+
+ return str - buf;
+}
+
+static DEVICE_ATTR(caps, S_IRUGO, show_caps, NULL);
+
+/*
+ * Device file system interface to the TPM
+ */
+int tpm_open(struct inode *inode, struct file *file)
+{
+ int rc = 0, minor = iminor(inode);
+ struct tpm_chip *chip = NULL, *pos;
+
+ spin_lock(&driver_lock);
+
+ list_for_each_entry(pos, &tpm_chip_list, list) {
+ if (pos->vendor->miscdev.minor == minor) {
+ chip = pos;
+ break;
+ }
+ }
+
+ if (chip == NULL) {
+ rc = -ENODEV;
+ goto err_out;
+ }
+
+ if (chip->num_opens) {
+ dev_dbg(&chip->pci_dev->dev,
+ "Another process owns this TPM\n");
+ rc = -EBUSY;
+ goto err_out;
+ }
+
+ chip->num_opens++;
+ pci_dev_get(chip->pci_dev);
+
+ spin_unlock(&driver_lock);
+
+ chip->data_buffer = kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL);
+ if (chip->data_buffer == NULL) {
+ chip->num_opens--;
+ pci_dev_put(chip->pci_dev);
+ return -ENOMEM;
+ }
+
+ atomic_set(&chip->data_pending, 0);
+
+ file->private_data = chip;
+ return 0;
+
+err_out:
+ spin_unlock(&driver_lock);
+ return rc;
+}
+
+EXPORT_SYMBOL_GPL(tpm_open);
+
+int tpm_release(struct inode *inode, struct file *file)
+{
+ struct tpm_chip *chip = file->private_data;
+
+ file->private_data = NULL;
+
+ spin_lock(&driver_lock);
+ chip->num_opens--;
+ spin_unlock(&driver_lock);
+
+ down(&chip->timer_manipulation_mutex);
+ if (timer_pending(&chip->user_read_timer))
+ del_singleshot_timer_sync(&chip->user_read_timer);
+ else if (timer_pending(&chip->device_timer))
+ del_singleshot_timer_sync(&chip->device_timer);
+ up(&chip->timer_manipulation_mutex);
+
+ kfree(chip->data_buffer);
+ atomic_set(&chip->data_pending, 0);
+
+ pci_dev_put(chip->pci_dev);
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(tpm_release);
+
+ssize_t tpm_write(struct file * file, const char __user * buf,
+ size_t size, loff_t * off)
+{
+ struct tpm_chip *chip = file->private_data;
+ int in_size = size, out_size;
+
+ /* cannot perform a write until the read has cleared
+ either via tpm_read or a user_read_timer timeout */
+ while (atomic_read(&chip->data_pending) != 0) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(TPM_TIMEOUT);
+ }
+
+ down(&chip->buffer_mutex);
+
+ if (in_size > TPM_BUFSIZE)
+ in_size = TPM_BUFSIZE;
+
+ if (copy_from_user
+ (chip->data_buffer, (void __user *) buf, in_size)) {
+ up(&chip->buffer_mutex);
+ return -EFAULT;
+ }
+
+ /* atomic tpm command send and result receive */
+ out_size = tpm_transmit(chip, chip->data_buffer, TPM_BUFSIZE);
+
+ atomic_set(&chip->data_pending, out_size);
+ atomic_set(&chip->data_position, 0);
+ up(&chip->buffer_mutex);
+
+ /* Set a timeout by which the reader must come claim the result */
+ down(&chip->timer_manipulation_mutex);
+ init_timer(&chip->user_read_timer);
+ chip->user_read_timer.function = user_reader_timeout;
+ chip->user_read_timer.data = (unsigned long) chip;
+ chip->user_read_timer.expires = jiffies + (60 * HZ);
+ add_timer(&chip->user_read_timer);
+ up(&chip->timer_manipulation_mutex);
+
+ return in_size;
+}
+
+EXPORT_SYMBOL_GPL(tpm_write);
+
+ssize_t tpm_read(struct file * file, char __user * buf,
+ size_t size, loff_t * off)
+{
+ struct tpm_chip *chip = file->private_data;
+ int ret_size = -ENODATA;
+ int pos, pending = 0;
+
+ down(&chip->buffer_mutex);
+ ret_size = atomic_read(&chip->data_pending);
+ if ( ret_size > 0 ) { /* Result available */
+ if (size < ret_size)
+ ret_size = size;
+
+ pos = atomic_read(&chip->data_position);
+
+ if (copy_to_user((void __user *) buf,
+ &chip->data_buffer[pos], ret_size)) {
+ ret_size = -EFAULT;
+ } else {
+ pending = atomic_read(&chip->data_pending) - ret_size;
+ if ( pending ) {
+ atomic_set( &chip->data_pending, pending );
+ atomic_set( &chip->data_position, pos+ret_size
);
+ }
+ }
+ }
+ up(&chip->buffer_mutex);
+
+ if ( ret_size <= 0 || pending == 0 ) {
+ atomic_set( &chip->data_pending, 0 );
+ down(&chip->timer_manipulation_mutex);
+ del_singleshot_timer_sync(&chip->user_read_timer);
+ up(&chip->timer_manipulation_mutex);
+ }
+
+ return ret_size;
+}
+
+EXPORT_SYMBOL_GPL(tpm_read);
+
+void __devexit tpm_remove(struct pci_dev *pci_dev)
+{
+ struct tpm_chip *chip = pci_get_drvdata(pci_dev);
+
+ if (chip == NULL) {
+ dev_err(&pci_dev->dev, "No device data found\n");
+ return;
+ }
+
+ spin_lock(&driver_lock);
+
+ list_del(&chip->list);
+
+ spin_unlock(&driver_lock);
+
+ pci_set_drvdata(pci_dev, NULL);
+ misc_deregister(&chip->vendor->miscdev);
+
+ device_remove_file(&pci_dev->dev, &dev_attr_pubek);
+ device_remove_file(&pci_dev->dev, &dev_attr_pcrs);
+ device_remove_file(&pci_dev->dev, &dev_attr_caps);
+
+ pci_disable_device(pci_dev);
+
+ dev_mask[chip->dev_num / 32] &= !(1 << (chip->dev_num % 32));
+
+ kfree(chip);
+
+ pci_dev_put(pci_dev);
+}
+
+EXPORT_SYMBOL_GPL(tpm_remove);
+
+static u8 savestate[] = {
+ 0, 193, /* TPM_TAG_RQU_COMMAND */
+ 0, 0, 0, 10, /* blob length (in bytes) */
+ 0, 0, 0, 152 /* TPM_ORD_SaveState */
+};
+
+/*
+ * We are about to suspend. Save the TPM state
+ * so that it can be restored.
+ */
+int tpm_pm_suspend(struct pci_dev *pci_dev, pm_message_t pm_state)
+{
+ struct tpm_chip *chip = pci_get_drvdata(pci_dev);
+ if (chip == NULL)
+ return -ENODEV;
+
+ tpm_transmit(chip, savestate, sizeof(savestate));
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(tpm_pm_suspend);
+
+/*
+ * Resume from a power safe. The BIOS already restored
+ * the TPM state.
+ */
+int tpm_pm_resume(struct pci_dev *pci_dev)
+{
+ struct tpm_chip *chip = pci_get_drvdata(pci_dev);
+
+ if (chip == NULL)
+ return -ENODEV;
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(tpm_pm_resume);
+
+/*
+ * Called from tpm_<specific>.c probe function only for devices
+ * the driver has determined it should claim. Prior to calling
+ * this function the specific probe function has called pci_enable_device
+ * upon errant exit from this function specific probe function should call
+ * pci_disable_device
+ */
+int tpm_register_hardware(struct pci_dev *pci_dev,
+ struct tpm_vendor_specific *entry)
+{
+ char devname[7];
+ struct tpm_chip *chip;
+ int i, j;
+
+ /* Driver specific per-device data */
+ chip = kmalloc(sizeof(*chip), GFP_KERNEL);
+ if (chip == NULL)
+ return -ENOMEM;
+
+ memset(chip, 0, sizeof(struct tpm_chip));
+
+ init_MUTEX(&chip->buffer_mutex);
+ init_MUTEX(&chip->tpm_mutex);
+ init_MUTEX(&chip->timer_manipulation_mutex);
+ INIT_LIST_HEAD(&chip->list);
+
+ chip->vendor = entry;
+
+ chip->dev_num = -1;
+
+ for (i = 0; i < 32; i++)
+ for (j = 0; j < 8; j++)
+ if ((dev_mask[i] & (1 << j)) == 0) {
+ chip->dev_num = i * 32 + j;
+ dev_mask[i] |= 1 << j;
+ goto dev_num_search_complete;
+ }
+
+dev_num_search_complete:
+ if (chip->dev_num < 0) {
+ dev_err(&pci_dev->dev,
+ "No available tpm device numbers\n");
+ kfree(chip);
+ return -ENODEV;
+ } else if (chip->dev_num == 0)
+ chip->vendor->miscdev.minor = TPM_MINOR;
+ else
+ chip->vendor->miscdev.minor = MISC_DYNAMIC_MINOR;
+
+ snprintf(devname, sizeof(devname), "%s%d", "tpm", chip->dev_num);
+ chip->vendor->miscdev.name = devname;
+
+ chip->vendor->miscdev.dev = &(pci_dev->dev);
+ chip->pci_dev = pci_dev_get(pci_dev);
+
+ if (misc_register(&chip->vendor->miscdev)) {
+ dev_err(&chip->pci_dev->dev,
+ "unable to misc_register %s, minor %d\n",
+ chip->vendor->miscdev.name,
+ chip->vendor->miscdev.minor);
+ pci_dev_put(pci_dev);
+ kfree(chip);
+ dev_mask[i] &= !(1 << j);
+ return -ENODEV;
+ }
+
+ pci_set_drvdata(pci_dev, chip);
+
+ list_add(&chip->list, &tpm_chip_list);
+
+ device_create_file(&pci_dev->dev, &dev_attr_pubek);
+ device_create_file(&pci_dev->dev, &dev_attr_pcrs);
+ device_create_file(&pci_dev->dev, &dev_attr_caps);
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(tpm_register_hardware);
+
+static int __init init_tpm(void)
+{
+ return 0;
+}
+
+static void __exit cleanup_tpm(void)
+{
+
+}
+
+module_init(init_tpm);
+module_exit(cleanup_tpm);
+
+MODULE_AUTHOR("Leendert van Doorn (leendert@xxxxxxxxxxxxxx)");
+MODULE_DESCRIPTION("TPM Driver");
+MODULE_VERSION("2.0");
+MODULE_LICENSE("GPL");
diff -r 84ab93e1ee05 -r dd668f7527cb linux-2.6-xen-sparse/drivers/char/tpm/tpm.h
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm.h Thu Sep 1 10:16:14 2005
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2004 IBM Corporation
+ *
+ * Authors:
+ * Leendert van Doorn <leendert@xxxxxxxxxxxxxx>
+ * Dave Safford <safford@xxxxxxxxxxxxxx>
+ * Reiner Sailer <sailer@xxxxxxxxxxxxxx>
+ * Kylene Hall <kjhall@xxxxxxxxxx>
+ *
+ * Maintained by: <tpmdd_devel@xxxxxxxxxxxxxxxxxxxxx>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ */
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+
+#define TPM_TIMEOUT msecs_to_jiffies(5)
+
+/* TPM addresses */
+#define TPM_ADDR 0x4E
+#define TPM_DATA 0x4F
+
+struct tpm_chip;
+
+struct tpm_vendor_specific {
+ u8 req_complete_mask;
+ u8 req_complete_val;
+ u16 base; /* TPM base address */
+
+ int (*recv) (struct tpm_chip *, u8 *, size_t);
+ int (*send) (struct tpm_chip *, u8 *, size_t);
+ void (*cancel) (struct tpm_chip *);
+ struct miscdevice miscdev;
+};
+
+struct tpm_chip {
+ struct pci_dev *pci_dev; /* PCI device stuff */
+
+ int dev_num; /* /dev/tpm# */
+ int num_opens; /* only one allowed */
+ int time_expired;
+
+ /* Data passed to and from the tpm via the read/write calls */
+ u8 *data_buffer;
+ atomic_t data_pending;
+ atomic_t data_position;
+ struct semaphore buffer_mutex;
+
+ struct timer_list user_read_timer; /* user needs to claim result */
+ struct semaphore tpm_mutex; /* tpm is processing */
+ struct timer_list device_timer; /* tpm is processing */
+ struct semaphore timer_manipulation_mutex;
+
+ struct tpm_vendor_specific *vendor;
+
+ struct list_head list;
+};
+
+static inline int tpm_read_index(int index)
+{
+ outb(index, TPM_ADDR);
+ return inb(TPM_DATA) & 0xFF;
+}
+
+static inline void tpm_write_index(int index, int value)
+{
+ outb(index, TPM_ADDR);
+ outb(value & 0xFF, TPM_DATA);
+}
+
+extern void tpm_time_expired(unsigned long);
+extern int tpm_register_hardware(struct pci_dev *,
+ struct tpm_vendor_specific *);
+extern int tpm_open(struct inode *, struct file *);
+extern int tpm_release(struct inode *, struct file *);
+extern ssize_t tpm_write(struct file *, const char __user *, size_t,
+ loff_t *);
+extern ssize_t tpm_read(struct file *, char __user *, size_t, loff_t *);
+extern void __devexit tpm_remove(struct pci_dev *);
+extern int tpm_pm_suspend(struct pci_dev *, pm_message_t);
+extern int tpm_pm_resume(struct pci_dev *);
diff -r 84ab93e1ee05 -r dd668f7527cb
linux-2.6-xen-sparse/drivers/char/tpm/tpm_atmel.c
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_atmel.c Thu Sep 1 10:16:14 2005
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2004 IBM Corporation
+ *
+ * Authors:
+ * Leendert van Doorn <leendert@xxxxxxxxxxxxxx>
+ * Dave Safford <safford@xxxxxxxxxxxxxx>
+ * Reiner Sailer <sailer@xxxxxxxxxxxxxx>
+ * Kylene Hall <kjhall@xxxxxxxxxx>
+ *
+ * Maintained by: <tpmdd_devel@xxxxxxxxxxxxxxxxxxxxx>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ */
+
+#include "tpm.h"
+
+/* Atmel definitions */
+enum tpm_atmel_addr {
+ TPM_ATMEL_BASE_ADDR_LO = 0x08,
+ TPM_ATMEL_BASE_ADDR_HI = 0x09
+};
+
+/* write status bits */
+#define ATML_STATUS_ABORT 0x01
+#define ATML_STATUS_LASTBYTE 0x04
+
+/* read status bits */
+#define ATML_STATUS_BUSY 0x01
+#define ATML_STATUS_DATA_AVAIL 0x02
+#define ATML_STATUS_REWRITE 0x04
+
+
+static int tpm_atml_recv(struct tpm_chip *chip, u8 * buf, size_t count)
+{
+ u8 status, *hdr = buf;
+ u32 size;
+ int i;
+ __be32 *native_size;
+
+ /* start reading header */
+ if (count < 6)
+ return -EIO;
+
+ for (i = 0; i < 6; i++) {
+ status = inb(chip->vendor->base + 1);
+ if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
+ dev_err(&chip->pci_dev->dev,
+ "error reading header\n");
+ return -EIO;
+ }
+ *buf++ = inb(chip->vendor->base);
+ }
+
+ /* size of the data received */
+ native_size = (__force __be32 *) (hdr + 2);
+ size = be32_to_cpu(*native_size);
+
+ if (count < size) {
+ dev_err(&chip->pci_dev->dev,
+ "Recv size(%d) less than available space\n", size);
+ for (; i < size; i++) { /* clear the waiting data anyway */
+ status = inb(chip->vendor->base + 1);
+ if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
+ dev_err(&chip->pci_dev->dev,
+ "error reading data\n");
+ return -EIO;
+ }
+ }
+ return -EIO;
+ }
+
+ /* read all the data available */
+ for (; i < size; i++) {
+ status = inb(chip->vendor->base + 1);
+ if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
+ dev_err(&chip->pci_dev->dev,
+ "error reading data\n");
+ return -EIO;
+ }
+ *buf++ = inb(chip->vendor->base);
+ }
+
+ /* make sure data available is gone */
+ status = inb(chip->vendor->base + 1);
+ if (status & ATML_STATUS_DATA_AVAIL) {
+ dev_err(&chip->pci_dev->dev, "data available is stuck\n");
+ return -EIO;
+ }
+
+ return size;
+}
+
+static int tpm_atml_send(struct tpm_chip *chip, u8 * buf, size_t count)
+{
+ int i;
+
+ dev_dbg(&chip->pci_dev->dev, "tpm_atml_send: ");
+ for (i = 0; i < count; i++) {
+ dev_dbg(&chip->pci_dev->dev, "0x%x(%d) ", buf[i], buf[i]);
+ outb(buf[i], chip->vendor->base);
+ }
+
+ return count;
+}
+
+static void tpm_atml_cancel(struct tpm_chip *chip)
+{
+ outb(ATML_STATUS_ABORT, chip->vendor->base + 1);
+}
+
+static struct file_operations atmel_ops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .open = tpm_open,
+ .read = tpm_read,
+ .write = tpm_write,
+ .release = tpm_release,
+};
+
+static struct tpm_vendor_specific tpm_atmel = {
+ .recv = tpm_atml_recv,
+ .send = tpm_atml_send,
+ .cancel = tpm_atml_cancel,
+ .req_complete_mask = ATML_STATUS_BUSY | ATML_STATUS_DATA_AVAIL,
+ .req_complete_val = ATML_STATUS_DATA_AVAIL,
+ .miscdev = { .fops = &atmel_ops, },
+};
+
+static int __devinit tpm_atml_init(struct pci_dev *pci_dev,
+ const struct pci_device_id *pci_id)
+{
+ u8 version[4];
+ int rc = 0;
+ int lo, hi;
+
+ if (pci_enable_device(pci_dev))
+ return -EIO;
+
+ lo = tpm_read_index( TPM_ATMEL_BASE_ADDR_LO );
+ hi = tpm_read_index( TPM_ATMEL_BASE_ADDR_HI );
+
+ tpm_atmel.base = (hi<<8)|lo;
+ dev_dbg( &pci_dev->dev, "Operating with base: 0x%x\n", tpm_atmel.base);
+
+ /* verify that it is an Atmel part */
+ if (tpm_read_index(4) != 'A' || tpm_read_index(5) != 'T'
+ || tpm_read_index(6) != 'M' || tpm_read_index(7) != 'L') {
+ rc = -ENODEV;
+ goto out_err;
+ }
+
+ /* query chip for its version number */
+ if ((version[0] = tpm_read_index(0x00)) != 0xFF) {
+ version[1] = tpm_read_index(0x01);
+ version[2] = tpm_read_index(0x02);
+ version[3] = tpm_read_index(0x03);
+ } else {
+ dev_info(&pci_dev->dev, "version query failed\n");
+ rc = -ENODEV;
+ goto out_err;
+ }
+
+ if ((rc = tpm_register_hardware(pci_dev, &tpm_atmel)) < 0)
+ goto out_err;
+
+ dev_info(&pci_dev->dev,
+ "Atmel TPM version %d.%d.%d.%d\n", version[0], version[1],
+ version[2], version[3]);
+
+ return 0;
+out_err:
+ pci_disable_device(pci_dev);
+ return rc;
+}
+
+static struct pci_device_id tpm_pci_tbl[] __devinitdata = {
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)},
+ {PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)},
+ {0,}
+};
+
+MODULE_DEVICE_TABLE(pci, tpm_pci_tbl);
+
+static struct pci_driver atmel_pci_driver = {
+ .name = "tpm_atmel",
+ .id_table = tpm_pci_tbl,
+ .probe = tpm_atml_init,
+ .remove = __devexit_p(tpm_remove),
+ .suspend = tpm_pm_suspend,
+ .resume = tpm_pm_resume,
+};
+
+static int __init init_atmel(void)
+{
+ return pci_register_driver(&atmel_pci_driver);
+}
+
+static void __exit cleanup_atmel(void)
+{
+ pci_unregister_driver(&atmel_pci_driver);
+}
+
+module_init(init_atmel);
+module_exit(cleanup_atmel);
+
+MODULE_AUTHOR("Leendert van Doorn (leendert@xxxxxxxxxxxxxx)");
+MODULE_DESCRIPTION("TPM Driver");
+MODULE_VERSION("2.0");
+MODULE_LICENSE("GPL");
diff -r 84ab93e1ee05 -r dd668f7527cb
linux-2.6-xen-sparse/drivers/char/tpm/tpm_nopci.c
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_nopci.c Thu Sep 1 10:16:14 2005
@@ -0,0 +1,741 @@
+/*
+ * Copyright (C) 2004 IBM Corporation
+ *
+ * Authors:
+ * Leendert van Doorn <leendert@xxxxxxxxxxxxxx>
+ * Dave Safford <safford@xxxxxxxxxxxxxx>
+ * Reiner Sailer <sailer@xxxxxxxxxxxxxx>
+ * Kylene Hall <kjhall@xxxxxxxxxx>
+ *
+ * Maintained by: <tpmdd_devel@xxxxxxxxxxxxxxxxxxxxx>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ * Note, the TPM chip is not interrupt driven (only polling)
+ * and can have very long timeouts (minutes!). Hence the unusual
+ * calls to schedule_timeout.
+ *
+ */
+
+#include <linux/sched.h>
+#include <linux/poll.h>
+#include <linux/spinlock.h>
+#include "tpm_nopci.h"
+
+enum {
+ TPM_MINOR = 224, /* officially assigned */
+ TPM_BUFSIZE = 2048,
+ TPM_NUM_DEVICES = 256,
+ TPM_NUM_MASK_ENTRIES = TPM_NUM_DEVICES / (8 * sizeof(int))
+};
+
+ /* PCI configuration addresses */
+enum {
+ PCI_GEN_PMCON_1 = 0xA0,
+ PCI_GEN1_DEC = 0xE4,
+ PCI_LPC_EN = 0xE6,
+ PCI_GEN2_DEC = 0xEC
+};
+
+enum {
+ TPM_LOCK_REG = 0x0D,
+ TPM_INTERUPT_REG = 0x0A,
+ TPM_BASE_ADDR_LO = 0x08,
+ TPM_BASE_ADDR_HI = 0x09,
+ TPM_UNLOCK_VALUE = 0x55,
+ TPM_LOCK_VALUE = 0xAA,
+ TPM_DISABLE_INTERUPT_VALUE = 0x00
+};
+
+static LIST_HEAD(tpm_chip_list);
+static spinlock_t driver_lock = SPIN_LOCK_UNLOCKED;
+static int dev_mask[32];
+
+static void user_reader_timeout(unsigned long ptr)
+{
+ struct tpm_chip *chip = (struct tpm_chip *) ptr;
+
+ down(&chip->buffer_mutex);
+ atomic_set(&chip->data_pending, 0);
+ memset(chip->data_buffer, 0, TPM_BUFSIZE);
+ up(&chip->buffer_mutex);
+}
+
+void tpm_time_expired(unsigned long ptr)
+{
+ int *exp = (int *) ptr;
+ *exp = 1;
+}
+
+EXPORT_SYMBOL_GPL(tpm_time_expired);
+
+
+/*
+ * This function should be used by other kernel subsystems attempting to use
the tpm through the tpm_transmit interface.
+ * A call to this function will return the chip structure corresponding to the
TPM you are looking for that can then be sent with your command to tpm_transmit.
+ * Passing 0 as the argument corresponds to /dev/tpm0 and thus the first and
probably primary TPM on the system. Passing 1 corresponds to /dev/tpm1 and the
next TPM discovered. If a TPM with the given chip_num does not exist NULL will
be returned.
+ */
+struct tpm_chip* tpm_chip_lookup(int chip_num)
+{
+
+ struct tpm_chip *pos;
+ list_for_each_entry(pos, &tpm_chip_list, list)
+ if (pos->dev_num == chip_num ||
+ chip_num == TPM_ANY_NUM)
+ return pos;
+
+ return NULL;
+
+}
+
+/*
+ * Internal kernel interface to transmit TPM commands
+ */
+ssize_t tpm_transmit(struct tpm_chip * chip, const char *buf,
+ size_t bufsiz)
+{
+ ssize_t rc;
+ u32 count;
+ unsigned long stop;
+
+ count = be32_to_cpu(*((__be32 *) (buf + 2)));
+
+ if (count == 0)
+ return -ENODATA;
+ if (count > bufsiz) {
+ dev_err(chip->dev,
+ "invalid count value %x %x \n", count, bufsiz);
+ return -E2BIG;
+ }
+
+ dev_dbg(chip->dev, "TPM Ordinal: %d\n",
+ be32_to_cpu(*((__be32 *) (buf + 6))));
+ dev_dbg(chip->dev, "Chip Status: %x\n",
+ inb(chip->vendor->base + 1));
+
+ down(&chip->tpm_mutex);
+
+ if ((rc = chip->vendor->send(chip, (u8 *) buf, count)) < 0) {
+ dev_err(chip->dev,
+ "tpm_transmit: tpm_send: error %d\n", rc);
+ goto out;
+ }
+
+ stop = jiffies + 2 * 60 * HZ;
+ do {
+ u8 status = chip->vendor->status(chip);
+ if ((status & chip->vendor->req_complete_mask) ==
+ chip->vendor->req_complete_val) {
+ goto out_recv;
+ }
+
+ if ((status == chip->vendor->req_canceled)) {
+ dev_err(chip->dev, "Operation Canceled\n");
+ rc = -ECANCELED;
+ goto out;
+ }
+
+ msleep(TPM_TIMEOUT); /* CHECK */
+ rmb();
+ }
+ while (time_before(jiffies, stop));
+
+
+ chip->vendor->cancel(chip);
+ dev_err(chip->dev, "Operation Timed out\n");
+ rc = -ETIME;
+ goto out;
+
+out_recv:
+ rc = chip->vendor->recv(chip, (u8 *) buf, bufsiz);
+ if (rc < 0)
+ dev_err(chip->dev,
+ "tpm_transmit: tpm_recv: error %d\n", rc);
+ atomic_set(&chip->data_position, 0);
+
+out:
+ up(&chip->tpm_mutex);
+ return rc;
+}
+
+EXPORT_SYMBOL_GPL(tpm_transmit);
+
+#define TPM_DIGEST_SIZE 20
+#define CAP_PCR_RESULT_SIZE 18
+static const u8 cap_pcr[] = {
+ 0, 193, /* TPM_TAG_RQU_COMMAND */
+ 0, 0, 0, 22, /* length */
+ 0, 0, 0, 101, /* TPM_ORD_GetCapability */
+ 0, 0, 0, 5,
+ 0, 0, 0, 4,
+ 0, 0, 1, 1
+};
+
+#define READ_PCR_RESULT_SIZE 30
+static const u8 pcrread[] = {
+ 0, 193, /* TPM_TAG_RQU_COMMAND */
+ 0, 0, 0, 14, /* length */
+ 0, 0, 0, 21, /* TPM_ORD_PcrRead */
+ 0, 0, 0, 0 /* PCR index */
+};
+
+ssize_t tpm_show_pcrs(struct device *dev, char *buf)
+{
+ u8 data[READ_PCR_RESULT_SIZE];
+ ssize_t len;
+ int i, j, num_pcrs;
+ __be32 index;
+ char *str = buf;
+
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, cap_pcr, sizeof(cap_pcr));
+ if ((len = tpm_transmit(chip, data, sizeof(data)))
+ < CAP_PCR_RESULT_SIZE)
+ return len;
+
+ num_pcrs = be32_to_cpu(*((__be32 *) (data + 14)));
+
+ for (i = 0; i < num_pcrs; i++) {
+ memcpy(data, pcrread, sizeof(pcrread));
+ index = cpu_to_be32(i);
+ memcpy(data + 10, &index, 4);
+ if ((len = tpm_transmit(chip, data, sizeof(data)))
+ < READ_PCR_RESULT_SIZE)
+ return len;
+ str += sprintf(str, "PCR-%02d: ", i);
+ for (j = 0; j < TPM_DIGEST_SIZE; j++)
+ str += sprintf(str, "%02X ", *(data + 10 + j));
+ str += sprintf(str, "\n");
+ }
+ return str - buf;
+}
+
+EXPORT_SYMBOL_GPL(tpm_show_pcrs);
+
+/*
+ * Return 0 on success. On error pass along error code.
+ * chip_id Upper 2 bytes equal ANY, HW_ONLY or SW_ONLY
+ * Lower 2 bytes equal tpm idx # or AN&
+ * res_buf must fit a TPM_PCR (20 bytes) or NULL if you don't care
+ */
+int tpm_pcr_read( u32 chip_id, int pcr_idx, u8* res_buf, int res_buf_size )
+{
+ u8 data[READ_PCR_RESULT_SIZE];
+ int rc;
+ __be32 index;
+ int chip_num = chip_id & TPM_CHIP_NUM_MASK;
+ struct tpm_chip* chip;
+
+ if ( res_buf && res_buf_size < TPM_DIGEST_SIZE )
+ return -ENOSPC;
+ if ( (chip = tpm_chip_lookup( chip_num /*,
+ chip_id >> TPM_CHIP_TYPE_SHIFT*/ ) ) ==
NULL ) {
+ printk("chip %d not found.\n",chip_num);
+ return -ENODEV;
+ }
+ memcpy(data, pcrread, sizeof(pcrread));
+ index = cpu_to_be32(pcr_idx);
+ memcpy(data + 10, &index, 4);
+ if ((rc = tpm_transmit(chip, data, sizeof(data))) > 0 )
+ rc = be32_to_cpu(*((u32*)(data+6)));
+
+ if ( rc == 0 && res_buf )
+ memcpy(res_buf, data+10, TPM_DIGEST_SIZE);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(tpm_pcr_read);
+
+#define EXTEND_PCR_SIZE 34
+static const u8 pcrextend[] = {
+ 0, 193, /* TPM_TAG_RQU_COMMAND
*/
+ 0, 0, 0, 34, /* length */
+ 0, 0, 0, 20, /* TPM_ORD_Extend */
+ 0, 0, 0, 0 /* PCR index */
+};
+
+/*
+ * Return 0 on success. On error pass along error code.
+ * chip_id Upper 2 bytes equal ANY, HW_ONLY or SW_ONLY
+ * Lower 2 bytes equal tpm idx # or ANY
+ */
+int tpm_pcr_extend(u32 chip_id, int pcr_idx, const u8* hash)
+{
+ u8 data[EXTEND_PCR_SIZE];
+ int rc;
+ __be32 index;
+ int chip_num = chip_id & TPM_CHIP_NUM_MASK;
+ struct tpm_chip* chip;
+
+ if ( (chip = tpm_chip_lookup( chip_num /*,
+ chip_id >> TPM_CHIP_TYPE_SHIFT */)) ==
NULL )
+ return -ENODEV;
+
+ memcpy(data, pcrextend, sizeof(pcrextend));
+ index = cpu_to_be32(pcr_idx);
+ memcpy(data + 10, &index, 4);
+ memcpy( data + 14, hash, TPM_DIGEST_SIZE );
+ if ((rc = tpm_transmit(chip, data, sizeof(data))) > 0 )
+ rc = be32_to_cpu(*((u32*)(data+6)));
+ return rc;
+}
+EXPORT_SYMBOL_GPL(tpm_pcr_extend);
+
+
+
+#define READ_PUBEK_RESULT_SIZE 314
+static const u8 readpubek[] = {
+ 0, 193, /* TPM_TAG_RQU_COMMAND */
+ 0, 0, 0, 30, /* length */
+ 0, 0, 0, 124, /* TPM_ORD_ReadPubek */
+};
+
+ssize_t tpm_show_pubek(struct device *dev, char *buf)
+{
+ u8 *data;
+ ssize_t len;
+ int i, rc;
+ char *str = buf;
+
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ if (chip == NULL)
+ return -ENODEV;
+
+ data = kmalloc(READ_PUBEK_RESULT_SIZE, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ memcpy(data, readpubek, sizeof(readpubek));
+ memset(data + sizeof(readpubek), 0, 20); /* zero nonce */
+
+ if ((len = tpm_transmit(chip, data, READ_PUBEK_RESULT_SIZE)) <
+ READ_PUBEK_RESULT_SIZE) {
+ rc = len;
+ goto out;
+ }
+
+ /*
+ ignore header 10 bytes
+ algorithm 32 bits (1 == RSA )
+ encscheme 16 bits
+ sigscheme 16 bits
+ parameters (RSA 12->bytes: keybit, #primes, expbit)
+ keylenbytes 32 bits
+ 256 byte modulus
+ ignore checksum 20 bytes
+ */
+
+ str +=
+ sprintf(str,
+ "Algorithm: %02X %02X %02X %02X\nEncscheme: %02X %02X\n"
+ "Sigscheme: %02X %02X\nParameters: %02X %02X %02X %02X"
+ " %02X %02X %02X %02X %02X %02X %02X %02X\n"
+ "Modulus length: %d\nModulus: \n",
+ data[10], data[11], data[12], data[13], data[14],
+ data[15], data[16], data[17], data[22], data[23],
+ data[24], data[25], data[26], data[27], data[28],
+ data[29], data[30], data[31], data[32], data[33],
+ be32_to_cpu(*((__be32 *) (data + 32))));
+
+ for (i = 0; i < 256; i++) {
+ str += sprintf(str, "%02X ", data[i + 39]);
+ if ((i + 1) % 16 == 0)
+ str += sprintf(str, "\n");
+ }
+ rc = str - buf;
+out:
+ kfree(data);
+ return rc;
+}
+
+EXPORT_SYMBOL_GPL(tpm_show_pubek);
+
+#define CAP_VER_RESULT_SIZE 18
+static const u8 cap_version[] = {
+ 0, 193, /* TPM_TAG_RQU_COMMAND */
+ 0, 0, 0, 18, /* length */
+ 0, 0, 0, 101, /* TPM_ORD_GetCapability */
+ 0, 0, 0, 6,
+ 0, 0, 0, 0
+};
+
+#define CAP_MANUFACTURER_RESULT_SIZE 18
+static const u8 cap_manufacturer[] = {
+ 0, 193, /* TPM_TAG_RQU_COMMAND */
+ 0, 0, 0, 22, /* length */
+ 0, 0, 0, 101, /* TPM_ORD_GetCapability */
+ 0, 0, 0, 5,
+ 0, 0, 0, 4,
+ 0, 0, 1, 3
+};
+
+ssize_t tpm_show_caps(struct device *dev, char *buf)
+{
+ u8 data[sizeof(cap_manufacturer)];
+ ssize_t len;
+ char *str = buf;
+
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, cap_manufacturer, sizeof(cap_manufacturer));
+
+ if ((len = tpm_transmit(chip, data, sizeof(data))) <
+ CAP_MANUFACTURER_RESULT_SIZE)
+ return len;
+
+ str += sprintf(str, "Manufacturer: 0x%x\n",
+ be32_to_cpu(*((__be32 *)(data + 14))));
+
+ memcpy(data, cap_version, sizeof(cap_version));
+
+ if ((len = tpm_transmit(chip, data, sizeof(data))) <
+ CAP_VER_RESULT_SIZE)
+ return len;
+
+ str +=
+ sprintf(str, "TCG version: %d.%d\nFirmware version: %d.%d\n",
+ (int) data[14], (int) data[15], (int) data[16],
+ (int) data[17]);
+
+ return str - buf;
+}
+
+EXPORT_SYMBOL_GPL(tpm_show_caps);
+
+ssize_t tpm_store_cancel(struct device * dev, const char *buf,
+ size_t count)
+{
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ if (chip == NULL)
+ return 0;
+
+ chip->vendor->cancel(chip);
+ return count;
+}
+
+EXPORT_SYMBOL_GPL(tpm_store_cancel);
+
+/*
+ * Device file system interface to the TPM
+ */
+int tpm_open(struct inode *inode, struct file *file)
+{
+ int rc = 0, minor = iminor(inode);
+ struct tpm_chip *chip = NULL, *pos;
+
+ spin_lock(&driver_lock);
+
+ list_for_each_entry(pos, &tpm_chip_list, list) {
+ if (pos->vendor->miscdev.minor == minor) {
+ chip = pos;
+ break;
+ }
+ }
+
+ if (chip == NULL) {
+ rc = -ENODEV;
+ goto err_out;
+ }
+
+ if (chip->num_opens) {
+ dev_dbg(chip->dev, "Another process owns this TPM\n");
+ rc = -EBUSY;
+ goto err_out;
+ }
+
+ chip->num_opens++;
+ get_device(chip->dev);
+
+ spin_unlock(&driver_lock);
+
+ chip->data_buffer = kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL);
+ if (chip->data_buffer == NULL) {
+ chip->num_opens--;
+ put_device(chip->dev);
+ return -ENOMEM;
+ }
+
+ atomic_set(&chip->data_pending, 0);
+
+ file->private_data = chip;
+ return 0;
+
+err_out:
+ spin_unlock(&driver_lock);
+ return rc;
+}
+
+EXPORT_SYMBOL_GPL(tpm_open);
+
+int tpm_release(struct inode *inode, struct file *file)
+{
+ struct tpm_chip *chip = file->private_data;
+
+ spin_lock(&driver_lock);
+ file->private_data = NULL;
+ chip->num_opens--;
+ del_singleshot_timer_sync(&chip->user_read_timer);
+ atomic_set(&chip->data_pending, 0);
+ put_device(chip->dev);
+ kfree(chip->data_buffer);
+ spin_unlock(&driver_lock);
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(tpm_release);
+
+ssize_t tpm_write(struct file * file, const char __user * buf,
+ size_t size, loff_t * off)
+{
+ struct tpm_chip *chip = file->private_data;
+ int in_size = size, out_size;
+
+ /* cannot perform a write until the read has cleared
+ either via tpm_read or a user_read_timer timeout */
+ while (atomic_read(&chip->data_pending) != 0)
+ msleep(TPM_TIMEOUT);
+
+ down(&chip->buffer_mutex);
+
+ if (in_size > TPM_BUFSIZE)
+ in_size = TPM_BUFSIZE;
+
+ if (copy_from_user
+ (chip->data_buffer, (void __user *) buf, in_size)) {
+ up(&chip->buffer_mutex);
+ return -EFAULT;
+ }
+
+ /* atomic tpm command send and result receive */
+ out_size = tpm_transmit(chip, chip->data_buffer, TPM_BUFSIZE);
+
+ atomic_set(&chip->data_pending, out_size);
+ up(&chip->buffer_mutex);
+
+ /* Set a timeout by which the reader must come claim the result */
+ mod_timer(&chip->user_read_timer, jiffies + (60 * HZ));
+
+ return in_size;
+}
+
+EXPORT_SYMBOL_GPL(tpm_write);
+
+ssize_t tpm_read(struct file * file, char __user * buf,
+ size_t size, loff_t * off)
+{
+ struct tpm_chip *chip = file->private_data;
+ int ret_size;
+
+ del_singleshot_timer_sync(&chip->user_read_timer);
+ ret_size = atomic_read(&chip->data_pending);
+
+ if (ret_size > 0) { /* relay data */
+ int position = atomic_read(&chip->data_position);
+
+ if (size < ret_size)
+ ret_size = size;
+
+ down(&chip->buffer_mutex);
+
+ if (copy_to_user((void __user *) buf,
+ &chip->data_buffer[position],
+ ret_size)) {
+ ret_size = -EFAULT;
+ } else {
+ int pending = atomic_read(&chip->data_pending) -
ret_size;
+ atomic_set(&chip->data_pending,
+ pending);
+ atomic_set(&chip->data_position,
+ position + ret_size);
+ }
+ up(&chip->buffer_mutex);
+ }
+
+ return ret_size;
+}
+
+EXPORT_SYMBOL_GPL(tpm_read);
+
+void tpm_remove_hardware(struct device *dev)
+{
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ int i;
+
+ if (chip == NULL) {
+ dev_err(dev, "No device data found\n");
+ return;
+ }
+
+ spin_lock(&driver_lock);
+
+ list_del(&chip->list);
+
+ spin_unlock(&driver_lock);
+
+ dev_set_drvdata(dev, NULL);
+ misc_deregister(&chip->vendor->miscdev);
+
+ for (i = 0; i < TPM_NUM_ATTR; i++)
+ device_remove_file(dev, &chip->vendor->attr[i]);
+
+ dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES] &=
+ !(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES));
+
+ kfree(chip);
+
+ put_device(dev);
+}
+
+EXPORT_SYMBOL_GPL(tpm_remove_hardware);
+
+static const u8 savestate[] = {
+ 0, 193, /* TPM_TAG_RQU_COMMAND */
+ 0, 0, 0, 10, /* blob length (in bytes) */
+ 0, 0, 0, 152 /* TPM_ORD_SaveState */
+};
+
+/*
+ * We are about to suspend. Save the TPM state
+ * so that it can be restored.
+ */
+int tpm_pm_suspend(struct pci_dev *pci_dev, u32 pm_state)
+{
+ struct tpm_chip *chip = pci_get_drvdata(pci_dev);
+ if (chip == NULL)
+ return -ENODEV;
+
+ tpm_transmit(chip, savestate, sizeof(savestate));
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(tpm_pm_suspend);
+
+/*
+ * Resume from a power safe. The BIOS already restored
+ * the TPM state.
+ */
+int tpm_pm_resume(struct pci_dev *pci_dev)
+{
+ struct tpm_chip *chip = pci_get_drvdata(pci_dev);
+
+ if (chip == NULL)
+ return -ENODEV;
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(tpm_pm_resume);
+
+/*
+ * Called from tpm_<specific>.c probe function only for devices
+ * the driver has determined it should claim. Prior to calling
+ * this function the specific probe function has called pci_enable_device
+ * upon errant exit from this function specific probe function should call
+ * pci_disable_device
+ */
+int tpm_register_hardware_nopci(struct device *dev,
+ struct tpm_vendor_specific *entry)
+{
+ char devname[7];
+ struct tpm_chip *chip;
+ int i, j;
+
+ /* Driver specific per-device data */
+ chip = kmalloc(sizeof(*chip), GFP_KERNEL);
+ if (chip == NULL)
+ return -ENOMEM;
+
+ memset(chip, 0, sizeof(struct tpm_chip));
+
+ init_MUTEX(&chip->buffer_mutex);
+ init_MUTEX(&chip->tpm_mutex);
+ INIT_LIST_HEAD(&chip->list);
+
+ init_timer(&chip->user_read_timer);
+ chip->user_read_timer.function = user_reader_timeout;
+ chip->user_read_timer.data = (unsigned long) chip;
+
+ chip->vendor = entry;
+
+ chip->dev_num = -1;
+
+ for (i = 0; i < TPM_NUM_MASK_ENTRIES; i++)
+ for (j = 0; j < 8 * sizeof(int); j++)
+ if ((dev_mask[i] & (1 << j)) == 0) {
+ chip->dev_num =
+ i * TPM_NUM_MASK_ENTRIES + j;
+ dev_mask[i] |= 1 << j;
+ goto dev_num_search_complete;
+ }
+
+dev_num_search_complete:
+ if (chip->dev_num < 0) {
+ dev_err(dev, "No available tpm device numbers\n");
+ kfree(chip);
+ return -ENODEV;
+ } else if (chip->dev_num == 0)
+ chip->vendor->miscdev.minor = TPM_MINOR;
+ else
+ chip->vendor->miscdev.minor = MISC_DYNAMIC_MINOR;
+
+ snprintf(devname, sizeof(devname), "%s%d", "tpm", chip->dev_num);
+ chip->vendor->miscdev.name = devname;
+
+ chip->vendor->miscdev.dev = dev;
+ chip->dev = get_device(dev);
+
+
+ if (misc_register(&chip->vendor->miscdev)) {
+ dev_err(chip->dev,
+ "unable to misc_register %s, minor %d\n",
+ chip->vendor->miscdev.name,
+ chip->vendor->miscdev.minor);
+ put_device(dev);
+ kfree(chip);
+ dev_mask[i] &= !(1 << j);
+ return -ENODEV;
+ }
+
+ spin_lock(&driver_lock);
+
+ dev_set_drvdata(dev, chip);
+
+ list_add(&chip->list, &tpm_chip_list);
+
+ spin_unlock(&driver_lock);
+
+ for (i = 0; i < TPM_NUM_ATTR; i++)
+ device_create_file(dev, &chip->vendor->attr[i]);
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(tpm_register_hardware_nopci);
+
+static int __init init_tpm(void)
+{
+ return 0;
+}
+
+static void __exit cleanup_tpm(void)
+{
+
+}
+
+module_init(init_tpm);
+module_exit(cleanup_tpm);
+
+MODULE_AUTHOR("Leendert van Doorn (leendert@xxxxxxxxxxxxxx)");
+MODULE_DESCRIPTION("TPM Driver");
+MODULE_VERSION("2.0");
+MODULE_LICENSE("GPL");
diff -r 84ab93e1ee05 -r dd668f7527cb
linux-2.6-xen-sparse/drivers/char/tpm/tpm_nopci.h
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_nopci.h Thu Sep 1 10:16:14 2005
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2004 IBM Corporation
+ *
+ * Authors:
+ * Leendert van Doorn <leendert@xxxxxxxxxxxxxx>
+ * Dave Safford <safford@xxxxxxxxxxxxxx>
+ * Reiner Sailer <sailer@xxxxxxxxxxxxxx>
+ * Kylene Hall <kjhall@xxxxxxxxxx>
+ *
+ * Maintained by: <tpmdd_devel@xxxxxxxxxxxxxxxxxxxxx>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ */
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/miscdevice.h>
+
+enum {
+ TPM_TIMEOUT = 5, /* msecs */
+ TPM_NUM_ATTR = 4
+};
+
+/* TPM addresses */
+enum {
+ TPM_ADDR = 0x4E,
+ TPM_DATA = 0x4F
+};
+
+/*
+ * Chip num is this value or a valid tpm idx in lower two bytes of chip_id
+ */
+enum tpm_chip_num {
+ TPM_ANY_NUM = 0xFFFF,
+};
+
+#define TPM_CHIP_NUM_MASK 0x0000ffff
+
+extern ssize_t tpm_show_pubek(struct device *, char *);
+extern ssize_t tpm_show_pcrs(struct device *, char *);
+extern ssize_t tpm_show_caps(struct device *, char *);
+extern ssize_t tpm_store_cancel(struct device *, const char *, size_t);
+
+#define TPM_DEVICE_ATTRS { \
+ __ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL), \
+ __ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL), \
+ __ATTR(caps, S_IRUGO, tpm_show_caps, NULL), \
+ __ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel) }
+
+struct tpm_chip;
+
+struct tpm_vendor_specific {
+ u8 req_complete_mask;
+ u8 req_complete_val;
+ u8 req_canceled;
+ u16 base; /* TPM base address */
+
+ int (*recv) (struct tpm_chip *, u8 *, size_t);
+ int (*send) (struct tpm_chip *, u8 *, size_t);
+ void (*cancel) (struct tpm_chip *);
+ u8(*status) (struct tpm_chip *);
+ struct miscdevice miscdev;
+ struct device_attribute attr[TPM_NUM_ATTR];
+};
+
+struct tpm_chip {
+ struct device *dev; /* PCI device stuff */
+
+ int dev_num; /* /dev/tpm# */
+ int num_opens; /* only one allowed */
+ int time_expired;
+
+ /* Data passed to and from the tpm via the read/write calls */
+ u8 *data_buffer;
+ atomic_t data_pending;
+ atomic_t data_position;
+ struct semaphore buffer_mutex;
+
+ struct timer_list user_read_timer; /* user needs to claim result */
+ struct semaphore tpm_mutex; /* tpm is processing */
+
+ struct tpm_vendor_specific *vendor;
+
+ struct list_head list;
+};
+
+static inline int tpm_read_index(int index)
+{
+ outb(index, TPM_ADDR);
+ return inb(TPM_DATA) & 0xFF;
+}
+
+static inline void tpm_write_index(int index, int value)
+{
+ outb(index, TPM_ADDR);
+ outb(value & 0xFF, TPM_DATA);
+}
+
+extern void tpm_time_expired(unsigned long);
+extern int tpm_lpc_bus_init(struct pci_dev *, u16);
+
+extern int tpm_register_hardware_nopci(struct device *,
+ struct tpm_vendor_specific *);
+extern void tpm_remove_hardware(struct device *);
+extern int tpm_open(struct inode *, struct file *);
+extern int tpm_release(struct inode *, struct file *);
+extern ssize_t tpm_write(struct file *, const char __user *, size_t,
+ loff_t *);
+extern ssize_t tpm_read(struct file *, char __user *, size_t, loff_t *);
+extern int tpm_pcr_extend(u32 chip_id, int pcr_idx, const u8* hash);
+extern int tpm_pcr_read( u32 chip_id, int pcr_idx, u8* res_buf, int
res_buf_size );
+
+extern int tpm_pm_suspend(struct pci_dev *, u32);
+extern int tpm_pm_resume(struct pci_dev *);
+
+/* internal kernel interface */
+extern ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
+ size_t bufsiz);
+extern struct tpm_chip *tpm_chip_lookup(int chip_num);
diff -r 84ab93e1ee05 -r dd668f7527cb
linux-2.6-xen-sparse/drivers/char/tpm/tpm_nsc.c
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_nsc.c Thu Sep 1 10:16:14 2005
@@ -0,0 +1,377 @@
+/*
+ * Copyright (C) 2004 IBM Corporation
+ *
+ * Authors:
+ * Leendert van Doorn <leendert@xxxxxxxxxxxxxx>
+ * Dave Safford <safford@xxxxxxxxxxxxxx>
+ * Reiner Sailer <sailer@xxxxxxxxxxxxxx>
+ * Kylene Hall <kjhall@xxxxxxxxxx>
+ *
+ * Maintained by: <tpmdd_devel@xxxxxxxxxxxxxxxxxxxxx>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ */
+
+#include "tpm.h"
+
+/* National definitions */
+#define TPM_NSC_BASE 0x360
+#define TPM_NSC_IRQ 0x07
+#define TPM_NSC_BASE0_HI 0x60
+#define TPM_NSC_BASE0_LO 0x61
+#define TPM_NSC_BASE1_HI 0x62
+#define TPM_NSC_BASE1_LO 0x63
+
+#define NSC_LDN_INDEX 0x07
+#define NSC_SID_INDEX 0x20
+#define NSC_LDC_INDEX 0x30
+#define NSC_DIO_INDEX 0x60
+#define NSC_CIO_INDEX 0x62
+#define NSC_IRQ_INDEX 0x70
+#define NSC_ITS_INDEX 0x71
+
+#define NSC_STATUS 0x01
+#define NSC_COMMAND 0x01
+#define NSC_DATA 0x00
+
+/* status bits */
+#define NSC_STATUS_OBF 0x01 /* output buffer full */
+#define NSC_STATUS_IBF 0x02 /* input buffer full */
+#define NSC_STATUS_F0 0x04 /* F0 */
+#define NSC_STATUS_A2 0x08 /* A2 */
+#define NSC_STATUS_RDY 0x10 /* ready to receive
command */
+#define NSC_STATUS_IBR 0x20 /* ready to receive
data */
+
+/* command bits */
+#define NSC_COMMAND_NORMAL 0x01 /* normal mode */
+#define NSC_COMMAND_EOC 0x03
+#define NSC_COMMAND_CANCEL 0x22
+
+/*
+ * Wait for a certain status to appear
+ */
+static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data)
+{
+ int expired = 0;
+ struct timer_list status_timer =
+ TIMER_INITIALIZER(tpm_time_expired, jiffies + 10 * HZ,
+ (unsigned long) &expired);
+
+ /* status immediately available check */
+ *data = inb(chip->vendor->base + NSC_STATUS);
+ if ((*data & mask) == val)
+ return 0;
+
+ /* wait for status */
+ add_timer(&status_timer);
+ do {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(TPM_TIMEOUT);
+ *data = inb(chip->vendor->base + 1);
+ if ((*data & mask) == val) {
+ del_singleshot_timer_sync(&status_timer);
+ return 0;
+ }
+ }
+ while (!expired);
+
+ return -EBUSY;
+}
+
+static int nsc_wait_for_ready(struct tpm_chip *chip)
+{
+ int status;
+ int expired = 0;
+ struct timer_list status_timer =
+ TIMER_INITIALIZER(tpm_time_expired, jiffies + 100,
+ (unsigned long) &expired);
+
+ /* status immediately available check */
+ status = inb(chip->vendor->base + NSC_STATUS);
+ if (status & NSC_STATUS_OBF)
+ status = inb(chip->vendor->base + NSC_DATA);
+ if (status & NSC_STATUS_RDY)
+ return 0;
+
+ /* wait for status */
+ add_timer(&status_timer);
+ do {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(TPM_TIMEOUT);
+ status = inb(chip->vendor->base + NSC_STATUS);
+ if (status & NSC_STATUS_OBF)
+ status = inb(chip->vendor->base + NSC_DATA);
+ if (status & NSC_STATUS_RDY) {
+ del_singleshot_timer_sync(&status_timer);
+ return 0;
+ }
+ }
+ while (!expired);
+
+ dev_info(&chip->pci_dev->dev, "wait for ready failed\n");
+ return -EBUSY;
+}
+
+
+static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count)
+{
+ u8 *buffer = buf;
+ u8 data, *p;
+ u32 size;
+ __be32 *native_size;
+
+ if (count < 6)
+ return -EIO;
+
+ if (wait_for_stat(chip, NSC_STATUS_F0, NSC_STATUS_F0, &data) < 0) {
+ dev_err(&chip->pci_dev->dev, "F0 timeout\n");
+ return -EIO;
+ }
+ if ((data =
+ inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_NORMAL) {
+ dev_err(&chip->pci_dev->dev, "not in normal mode (0x%x)\n",
+ data);
+ return -EIO;
+ }
+
+ /* read the whole packet */
+ for (p = buffer; p < &buffer[count]; p++) {
+ if (wait_for_stat
+ (chip, NSC_STATUS_OBF, NSC_STATUS_OBF, &data) < 0) {
+ dev_err(&chip->pci_dev->dev,
+ "OBF timeout (while reading data)\n");
+ return -EIO;
+ }
+ if (data & NSC_STATUS_F0)
+ break;
+ *p = inb(chip->vendor->base + NSC_DATA);
+ }
+
+ if ((data & NSC_STATUS_F0) == 0) {
+ dev_err(&chip->pci_dev->dev, "F0 not set\n");
+ return -EIO;
+ }
+ if ((data = inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_EOC) {
+ dev_err(&chip->pci_dev->dev,
+ "expected end of command(0x%x)\n", data);
+ return -EIO;
+ }
+
+ native_size = (__force __be32 *) (buf + 2);
+ size = be32_to_cpu(*native_size);
+
+ if (count < size)
+ return -EIO;
+
+ return size;
+}
+
+static int tpm_nsc_send(struct tpm_chip *chip, u8 * buf, size_t count)
+{
+ u8 data;
+ int i;
+
+ /*
+ * If we hit the chip with back to back commands it locks up
+ * and never set IBF. Hitting it with this "hammer" seems to
+ * fix it. Not sure why this is needed, we followed the flow
+ * chart in the manual to the letter.
+ */
+ outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND);
+
+ if (nsc_wait_for_ready(chip) != 0)
+ return -EIO;
+
+ if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
+ dev_err(&chip->pci_dev->dev, "IBF timeout\n");
+ return -EIO;
+ }
+
+ outb(NSC_COMMAND_NORMAL, chip->vendor->base + NSC_COMMAND);
+ if (wait_for_stat(chip, NSC_STATUS_IBR, NSC_STATUS_IBR, &data) < 0) {
+ dev_err(&chip->pci_dev->dev, "IBR timeout\n");
+ return -EIO;
+ }
+
+ for (i = 0; i < count; i++) {
+ if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
+ dev_err(&chip->pci_dev->dev,
+ "IBF timeout (while writing data)\n");
+ return -EIO;
+ }
+ outb(buf[i], chip->vendor->base + NSC_DATA);
+ }
+
+ if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
+ dev_err(&chip->pci_dev->dev, "IBF timeout\n");
+ return -EIO;
+ }
+ outb(NSC_COMMAND_EOC, chip->vendor->base + NSC_COMMAND);
+
+ return count;
+}
+
+static void tpm_nsc_cancel(struct tpm_chip *chip)
+{
+ outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND);
+}
+
+static struct file_operations nsc_ops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .open = tpm_open,
+ .read = tpm_read,
+ .write = tpm_write,
+ .release = tpm_release,
+};
+
+static struct tpm_vendor_specific tpm_nsc = {
+ .recv = tpm_nsc_recv,
+ .send = tpm_nsc_send,
+ .cancel = tpm_nsc_cancel,
+ .req_complete_mask = NSC_STATUS_OBF,
+ .req_complete_val = NSC_STATUS_OBF,
+ .miscdev = { .fops = &nsc_ops, },
+
+};
+
+static int __devinit tpm_nsc_init(struct pci_dev *pci_dev,
+ const struct pci_device_id *pci_id)
+{
+ int rc = 0;
+ int lo, hi;
+
+ hi = tpm_read_index(TPM_NSC_BASE0_HI);
+ lo = tpm_read_index(TPM_NSC_BASE0_LO);
+
+ tpm_nsc.base = (hi<<8) | lo;
+
+ if (pci_enable_device(pci_dev))
+ return -EIO;
+
+ /* verify that it is a National part (SID) */
+ if (tpm_read_index(NSC_SID_INDEX) != 0xEF) {
+ rc = -ENODEV;
+ goto out_err;
+ }
+
+ dev_dbg(&pci_dev->dev, "NSC TPM detected\n");
+ dev_dbg(&pci_dev->dev,
+ "NSC LDN 0x%x, SID 0x%x, SRID 0x%x\n",
+ tpm_read_index(0x07), tpm_read_index(0x20),
+ tpm_read_index(0x27));
+ dev_dbg(&pci_dev->dev,
+ "NSC SIOCF1 0x%x SIOCF5 0x%x SIOCF6 0x%x SIOCF8 0x%x\n",
+ tpm_read_index(0x21), tpm_read_index(0x25),
+ tpm_read_index(0x26), tpm_read_index(0x28));
+ dev_dbg(&pci_dev->dev, "NSC IO Base0 0x%x\n",
+ (tpm_read_index(0x60) << 8) | tpm_read_index(0x61));
+ dev_dbg(&pci_dev->dev, "NSC IO Base1 0x%x\n",
+ (tpm_read_index(0x62) << 8) | tpm_read_index(0x63));
+ dev_dbg(&pci_dev->dev, "NSC Interrupt number and wakeup 0x%x\n",
+ tpm_read_index(0x70));
+ dev_dbg(&pci_dev->dev, "NSC IRQ type select 0x%x\n",
+ tpm_read_index(0x71));
+ dev_dbg(&pci_dev->dev,
+ "NSC DMA channel select0 0x%x, select1 0x%x\n",
+ tpm_read_index(0x74), tpm_read_index(0x75));
+ dev_dbg(&pci_dev->dev,
+ "NSC Config "
+ "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+ tpm_read_index(0xF0), tpm_read_index(0xF1),
+ tpm_read_index(0xF2), tpm_read_index(0xF3),
+ tpm_read_index(0xF4), tpm_read_index(0xF5),
+ tpm_read_index(0xF6), tpm_read_index(0xF7),
+ tpm_read_index(0xF8), tpm_read_index(0xF9));
+
+ dev_info(&pci_dev->dev,
+ "NSC PC21100 TPM revision %d\n",
+ tpm_read_index(0x27) & 0x1F);
+
+ if (tpm_read_index(NSC_LDC_INDEX) == 0)
+ dev_info(&pci_dev->dev, ": NSC TPM not active\n");
+
+ /* select PM channel 1 */
+ tpm_write_index(NSC_LDN_INDEX, 0x12);
+ tpm_read_index(NSC_LDN_INDEX);
+
+ /* disable the DPM module */
+ tpm_write_index(NSC_LDC_INDEX, 0);
+ tpm_read_index(NSC_LDC_INDEX);
+
+ /* set the data register base addresses */
+ tpm_write_index(NSC_DIO_INDEX, TPM_NSC_BASE >> 8);
+ tpm_write_index(NSC_DIO_INDEX + 1, TPM_NSC_BASE);
+ tpm_read_index(NSC_DIO_INDEX);
+ tpm_read_index(NSC_DIO_INDEX + 1);
+
+ /* set the command register base addresses */
+ tpm_write_index(NSC_CIO_INDEX, (TPM_NSC_BASE + 1) >> 8);
+ tpm_write_index(NSC_CIO_INDEX + 1, (TPM_NSC_BASE + 1));
+ tpm_read_index(NSC_DIO_INDEX);
+ tpm_read_index(NSC_DIO_INDEX + 1);
+
+ /* set the interrupt number to be used for the host interface */
+ tpm_write_index(NSC_IRQ_INDEX, TPM_NSC_IRQ);
+ tpm_write_index(NSC_ITS_INDEX, 0x00);
+ tpm_read_index(NSC_IRQ_INDEX);
+
+ /* enable the DPM module */
+ tpm_write_index(NSC_LDC_INDEX, 0x01);
+ tpm_read_index(NSC_LDC_INDEX);
+
+ if ((rc = tpm_register_hardware(pci_dev, &tpm_nsc)) < 0)
+ goto out_err;
+
+ return 0;
+
+out_err:
+ pci_disable_device(pci_dev);
+ return rc;
+}
+
+static struct pci_device_id tpm_pci_tbl[] __devinitdata = {
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)},
+ {PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)},
+ {0,}
+};
+
+MODULE_DEVICE_TABLE(pci, tpm_pci_tbl);
+
+static struct pci_driver nsc_pci_driver = {
+ .name = "tpm_nsc",
+ .id_table = tpm_pci_tbl,
+ .probe = tpm_nsc_init,
+ .remove = __devexit_p(tpm_remove),
+ .suspend = tpm_pm_suspend,
+ .resume = tpm_pm_resume,
+};
+
+static int __init init_nsc(void)
+{
+ return pci_register_driver(&nsc_pci_driver);
+}
+
+static void __exit cleanup_nsc(void)
+{
+ pci_unregister_driver(&nsc_pci_driver);
+}
+
+module_init(init_nsc);
+module_exit(cleanup_nsc);
+
+MODULE_AUTHOR("Leendert van Doorn (leendert@xxxxxxxxxxxxxx)");
+MODULE_DESCRIPTION("TPM Driver");
+MODULE_VERSION("2.0");
+MODULE_LICENSE("GPL");
diff -r 84ab93e1ee05 -r dd668f7527cb
linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c Thu Sep 1 10:16:14 2005
@@ -0,0 +1,513 @@
+/*
+ * Copyright (C) 2004 IBM Corporation
+ *
+ * Authors:
+ * Leendert van Doorn <leendert@xxxxxxxxxxxxxx>
+ * Dave Safford <safford@xxxxxxxxxxxxxx>
+ * Reiner Sailer <sailer@xxxxxxxxxxxxxx>
+ * Kylene Hall <kjhall@xxxxxxxxxx>
+ * Stefan Berger <stefanb@xxxxxxxxxx>
+ *
+ * Maintained by: <tpmdd_devel@xxxxxxxxxxxxxxxxxxxxx>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module) for XEN.
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ */
+
+#include <asm/uaccess.h>
+#include <linux/list.h>
+#include <linux/tpmfe.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include "tpm_nopci.h"
+
+/* read status bits */
+enum {
+ STATUS_BUSY = 0x01,
+ STATUS_DATA_AVAIL = 0x02,
+ STATUS_READY = 0x04
+};
+
+#define MIN(x,y) ((x) < (y)) ? (x) : (y)
+
+struct transmission {
+ struct list_head next;
+ unsigned char *request;
+ unsigned int request_len;
+ unsigned char *rcv_buffer;
+ unsigned int buffersize;
+ struct tpm_chip *chip;
+ unsigned int flags;
+};
+
+enum {
+ TRANSMISSION_FLAG_WAS_QUEUED = 0x1
+};
+
+struct data_exchange {
+ struct transmission *current_request;
+ spinlock_t req_list_lock;
+ wait_queue_head_t req_wait_queue;
+
+ struct list_head queued_requests;
+
+ struct transmission *current_response;
+ spinlock_t resp_list_lock;
+ wait_queue_head_t resp_wait_queue; // processes waiting for
responses
+
+ struct transmission *req_cancelled; // if a cancellation was
encounterd
+
+ unsigned int fe_status;
+ unsigned int flags;
+};
+
+enum {
+ DATAEX_FLAG_QUEUED_ONLY = 0x1
+};
+
+static struct data_exchange dataex;
+
+static unsigned long disconnect_time;
+
+/* local function prototypes */
+static void __exit cleanup_xen(void);
+
+
+/* =============================================================
+ * Some utility functions
+ * =============================================================
+ */
+static inline struct transmission *
+transmission_alloc(void)
+{
+ struct transmission *t = kmalloc(sizeof(*t), GFP_KERNEL);
+ if (t) {
+ memset(t, 0x0, sizeof(*t));
+ }
+ return t;
+}
+
+static inline unsigned char *
+transmission_set_buffer(struct transmission *t,
+ unsigned char *buffer, unsigned int len)
+{
+ if (NULL != t->request) {
+ kfree(t->request);
+ }
+ t->request = kmalloc(len, GFP_KERNEL);
+ if (t->request) {
+ memcpy(t->request,
+ buffer,
+ len);
+ t->request_len = len;
+ }
+ return t->request;
+}
+
+static inline void
+transmission_free(struct transmission *t)
+{
+ if (t->request) {
+ kfree(t->request);
+ }
+ if (t->rcv_buffer) {
+ kfree(t->rcv_buffer);
+ }
+ kfree(t);
+}
+
+/* =============================================================
+ * Interface with the TPM shared memory driver for XEN
+ * =============================================================
+ */
+static int tpm_recv(const u8 *buffer, size_t count, const void *ptr)
+{
+ int ret_size = 0;
+ struct transmission *t, *temp;
+
+ /*
+ * The list with requests must contain one request
+ * only and the element there must be the one that
+ * was passed to me from the front-end.
+ */
+ if (dataex.current_request != ptr) {
+ printk("WARNING: The request pointer is different than the
pointer "
+ "the shared memory driver returned to me. %p != %p\n",
+ dataex.current_request, ptr);
+ }
+
+ /*
+ * If the request has been cancelled, just quit here
+ */
+ if (dataex.req_cancelled == (struct transmission *)ptr) {
+ if (dataex.current_request == dataex.req_cancelled) {
+ dataex.current_request = NULL;
+ }
+ transmission_free(dataex.req_cancelled);
+ dataex.req_cancelled = NULL;
+ return 0;
+ }
+
+ if (NULL != (temp = dataex.current_request)) {
+ transmission_free(temp);
+ dataex.current_request = NULL;
+ }
+
+ t = transmission_alloc();
+ if (NULL != t) {
+ unsigned long flags;
+ t->rcv_buffer = kmalloc(count, GFP_KERNEL);
+ if (NULL == t->rcv_buffer) {
+ transmission_free(t);
+ return -ENOMEM;
+ }
+ t->buffersize = count;
+ memcpy(t->rcv_buffer, buffer, count);
+ ret_size = count;
+
+ spin_lock_irqsave(&dataex.resp_list_lock ,flags);
+ dataex.current_response = t;
+ spin_unlock_irqrestore(&dataex.resp_list_lock, flags);
+ wake_up_interruptible(&dataex.resp_wait_queue);
+ }
+ return ret_size;
+}
+
+
+static void tpm_fe_status(unsigned int flags)
+{
+ dataex.fe_status = flags;
+ if ((dataex.fe_status & TPMFE_STATUS_CONNECTED) == 0) {
+ disconnect_time = jiffies;
+ }
+}
+
+/* =============================================================
+ * Interface with the generic TPM driver
+ * =============================================================
+ */
+static int tpm_xen_recv(struct tpm_chip *chip, u8 * buf, size_t count)
+{
+ unsigned long flags;
+ int rc = 0;
+
+ spin_lock_irqsave(&dataex.resp_list_lock, flags);
+ /*
+ * Check if the previous operation only queued the command
+ * In this case there won't be a response, so I just
+ * return from here and reset that flag. In any other
+ * case I should receive a response from the back-end.
+ */
+ if ((dataex.flags & DATAEX_FLAG_QUEUED_ONLY) != 0) {
+ dataex.flags &= ~DATAEX_FLAG_QUEUED_ONLY;
+ spin_unlock_irqrestore(&dataex.resp_list_lock, flags);
+ /*
+ * a little hack here. The first few measurements
+ * are queued since there's no way to talk to the
+ * TPM yet (due to slowness of the control channel)
+ * So we just make IMA happy by giving it 30 NULL
+ * bytes back where the most important part is
+ * that the result code is '0'.
+ */
+
+ count = MIN(count, 30);
+ memset(buf, 0x0, count);
+ return count;
+ }
+ /*
+ * Check whether something is in the responselist and if
+ * there's nothing in the list wait for something to appear.
+ */
+
+ if (NULL == dataex.current_response) {
+ spin_unlock_irqrestore(&dataex.resp_list_lock, flags);
+ interruptible_sleep_on_timeout(&dataex.resp_wait_queue,
+ 1000);
+ spin_lock_irqsave(&dataex.resp_list_lock ,flags);
+ }
+
+ if (NULL != dataex.current_response) {
+ struct transmission *t = dataex.current_response;
+ dataex.current_response = NULL;
+ rc = MIN(count, t->buffersize);
+ memcpy(buf, t->rcv_buffer, rc);
+ transmission_free(t);
+ }
+
+ spin_unlock_irqrestore(&dataex.resp_list_lock, flags);
+ return rc;
+}
+
+static int tpm_xen_send(struct tpm_chip *chip, u8 * buf, size_t count)
+{
+ /*
+ * We simply pass the packet onto the XEN shared
+ * memory driver.
+ */
+ unsigned long flags;
+ int rc;
+ struct transmission *t = transmission_alloc();
+
+ spin_lock_irqsave(&dataex.req_list_lock, flags);
+ /*
+ * If there's a current request, it must be the
+ * previous request that has timed out.
+ */
+ if (dataex.current_request != NULL) {
+ printk("WARNING: Sending although there is a request
outstanding.\n"
+ " Previous request must have timed out.\n");
+ transmission_free(dataex.current_request);
+ dataex.current_request = NULL;
+ }
+
+ if (t != NULL) {
+ unsigned int error = 0;
+ t->rcv_buffer = NULL;
+ t->buffersize = 0;
+ t->chip = chip;
+
+ /*
+ * Queue the packet if the driver below is not
+ * ready, yet, or there is any packet already
+ * in the queue.
+ * If the driver below is ready, unqueue all
+ * packets first before sending our current
+ * packet.
+ * For each unqueued packet, except for the
+ * last (=current) packet, call the function
+ * tpm_xen_recv to wait for the response to come
+ * back.
+ */
+ if ((dataex.fe_status & TPMFE_STATUS_CONNECTED) == 0) {
+ if (time_after(jiffies, disconnect_time + HZ * 10)) {
+ rc = -ENOENT;
+ } else {
+ /*
+ * copy the request into the buffer
+ */
+ if (transmission_set_buffer(t, buf, count)
+ == NULL) {
+ transmission_free(t);
+ rc = -ENOMEM;
+ goto exit;
+ }
+ dataex.flags |= DATAEX_FLAG_QUEUED_ONLY;
+ list_add_tail(&t->next,
&dataex.queued_requests);
+ rc = 0;
+ }
+ } else {
+ /*
+ * Check whether there are any packets in the queue
+ */
+ while (!list_empty(&dataex.queued_requests)) {
+ /*
+ * Need to dequeue them.
+ * Read the result into a dummy buffer.
+ */
+ unsigned char buffer[1];
+ struct transmission *qt = (struct transmission
*) dataex.queued_requests.next;
+ list_del(&qt->next);
+ dataex.current_request = qt;
+ spin_unlock_irqrestore(&dataex.req_list_lock,
flags);
+
+ rc = tpm_fe_send(qt->request,
+ qt->request_len,
+ qt);
+
+ if (rc < 0) {
+
spin_lock_irqsave(&dataex.req_list_lock, flags);
+ if ((qt = dataex.current_request) !=
NULL) {
+ /*
+ * requeue it at the beginning
+ * of the list
+ */
+ list_add(&qt->next,
+
&dataex.queued_requests);
+ }
+ dataex.current_request = NULL;
+ error = 1;
+ break;
+ }
+ /*
+ * After this point qt is not valid anymore!
+ * It is freed when the front-end is delivering
the data
+ * by calling tpm_recv
+ */
+
+ /*
+ * Try to receive the response now into the
provided dummy
+ * buffer (I don't really care about this
response since
+ * there is no receiver anymore for this
response)
+ */
+ rc = tpm_xen_recv(chip, buffer, sizeof(buffer));
+
+ spin_lock_irqsave(&dataex.req_list_lock, flags);
+ }
+
+ if (error == 0) {
+ /*
+ * Finally, send the current request.
+ */
+ dataex.current_request = t;
+ /*
+ * Call the shared memory driver
+ * Pass to it the buffer with the request, the
+ * amount of bytes in the request and
+ * a void * pointer (here: transmission
structure)
+ */
+ rc = tpm_fe_send(buf, count, t);
+ /*
+ * The generic TPM driver will call
+ * the function to receive the response.
+ */
+ if (rc < 0) {
+ dataex.current_request = NULL;
+ goto queue_it;
+ }
+ } else {
+queue_it:
+ if (transmission_set_buffer(t, buf, count) ==
NULL) {
+ transmission_free(t);
+ rc = -ENOMEM;
+ goto exit;
+ }
+ /*
+ * An error occurred. Don't event try
+ * to send the current request. Just
+ * queue it.
+ */
+ dataex.flags |= DATAEX_FLAG_QUEUED_ONLY;
+ list_add_tail(&t->next,
&dataex.queued_requests);
+ rc = 0;
+ }
+ }
+ } else {
+ rc = -ENOMEM;
+ }
+
+exit:
+ spin_unlock_irqrestore(&dataex.req_list_lock, flags);
+ return rc;
+}
+
+static void tpm_xen_cancel(struct tpm_chip *chip)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&dataex.resp_list_lock,flags);
+
+ dataex.req_cancelled = dataex.current_request;
+
+ spin_unlock_irqrestore(&dataex.resp_list_lock,flags);
+}
+
+static u8 tpm_xen_status(struct tpm_chip *chip)
+{
+ unsigned long flags;
+ u8 rc = 0;
+ spin_lock_irqsave(&dataex.resp_list_lock, flags);
+ /*
+ * Data are available if:
+ * - there's a current response
+ * - the last packet was queued only (this is fake, but necessary to
+ * get the generic TPM layer to call the receive function.)
+ */
+ if (NULL != dataex.current_response ||
+ 0 != (dataex.flags & DATAEX_FLAG_QUEUED_ONLY)) {
+ rc = STATUS_DATA_AVAIL;
+ }
+ spin_unlock_irqrestore(&dataex.resp_list_lock, flags);
+ return rc;
+}
+
+static struct file_operations tpm_xen_ops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .open = tpm_open,
+ .read = tpm_read,
+ .write = tpm_write,
+ .release = tpm_release,
+};
+
+static struct tpm_vendor_specific tpm_xen = {
+ .recv = tpm_xen_recv,
+ .send = tpm_xen_send,
+ .cancel = tpm_xen_cancel,
+ .status = tpm_xen_status,
+ .req_complete_mask = STATUS_BUSY | STATUS_DATA_AVAIL,
+ .req_complete_val = STATUS_DATA_AVAIL,
+ .req_canceled = STATUS_READY,
+ .base = 0,
+ .attr = TPM_DEVICE_ATTRS,
+ .miscdev.fops = &tpm_xen_ops,
+};
+
+static struct device tpm_device = {
+ .bus_id = "vtpm",
+};
+
+static struct tpmfe_device tpmfe = {
+ .receive = tpm_recv,
+ .status = tpm_fe_status,
+};
+
+
+static int __init init_xen(void)
+{
+ int rc;
+
+ /*
+ * Register device with the low lever front-end
+ * driver
+ */
+ if ((rc = tpm_fe_register_receiver(&tpmfe)) < 0) {
+ return rc;
+ }
+
+ /*
+ * Register our device with the system.
+ */
+ if ((rc = device_register(&tpm_device)) < 0) {
+ tpm_fe_unregister_receiver();
+ return rc;
+ }
+
+ if ((rc = tpm_register_hardware_nopci(&tpm_device, &tpm_xen)) < 0) {
+ device_unregister(&tpm_device);
+ tpm_fe_unregister_receiver();
+ return rc;
+ }
+
+ dataex.current_request = NULL;
+ spin_lock_init(&dataex.req_list_lock);
+ init_waitqueue_head(&dataex.req_wait_queue);
+ INIT_LIST_HEAD(&dataex.queued_requests);
+
+ dataex.current_response = NULL;
+ spin_lock_init(&dataex.resp_list_lock);
+ init_waitqueue_head(&dataex.resp_wait_queue);
+
+ disconnect_time = jiffies;
+
+ return 0;
+}
+
+static void __exit cleanup_xen(void)
+{
+ tpm_remove_hardware(&tpm_device);
+ device_unregister(&tpm_device);
+ tpm_fe_unregister_receiver();
+}
+
+fs_initcall(init_xen);
+module_exit(cleanup_xen);
+
+MODULE_AUTHOR("Stefan Berger (stefanb@xxxxxxxxxx)");
+MODULE_DESCRIPTION("TPM Driver for XEN (shared memory)");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff -r 84ab93e1ee05 -r dd668f7527cb
linux-2.6-xen-sparse/drivers/xen/tpmback/Makefile
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/Makefile Thu Sep 1 10:16:14 2005
@@ -0,0 +1,4 @@
+
+obj-$(CONFIG_XEN_TPMDEV_BACKEND) += tpmbk.o
+
+tpmbk-y += tpmback.o interface.o xenbus.o
diff -r 84ab93e1ee05 -r dd668f7527cb
linux-2.6-xen-sparse/drivers/xen/tpmback/common.h
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h Thu Sep 1 10:16:14 2005
@@ -0,0 +1,89 @@
+/******************************************************************************
+ * drivers/xen/tpmback/common.h
+ */
+
+#ifndef __NETIF__BACKEND__COMMON_H__
+#define __NETIF__BACKEND__COMMON_H__
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <asm-xen/ctrl_if.h>
+#include <asm-xen/evtchn.h>
+#include <asm-xen/xen-public/io/tpmif.h>
+#include <asm/io.h>
+#include <asm/pgalloc.h>
+#include <asm-xen/xen-public/io/domain_controller.h>
+
+#if 0
+#define ASSERT(_p) \
+ if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , \
+ __LINE__, __FILE__); *(int*)0=0; }
+#define DPRINTK(_f, _a...) printk(KERN_ALERT "(file=%s, line=%d) " _f, \
+ __FILE__ , __LINE__ , ## _a )
+#else
+#define ASSERT(_p) ((void)0)
+#define DPRINTK(_f, _a...) ((void)0)
+#endif
+
+typedef struct tpmif_st {
+ struct list_head tpmif_list;
+ /* Unique identifier for this interface. */
+ domid_t domid;
+ unsigned int handle;
+
+ /* Physical parameters of the comms window. */
+ unsigned long tx_shmem_frame;
+ unsigned int evtchn;
+ unsigned int remote_evtchn;
+
+ /* The shared rings and indexes. */
+ tpmif_tx_interface_t *tx;
+
+ /* Miscellaneous private stuff. */
+ enum { DISCONNECTED, DISCONNECTING, CONNECTED } status;
+ int active;
+
+ struct tpmif_st *hash_next;
+ struct list_head list; /* scheduling list */
+ atomic_t refcnt;
+
+ long int tpm_instance;
+ unsigned long mmap_vstart;
+
+ struct work_struct work;
+
+ u16 shmem_handle;
+ unsigned long shmem_vaddr;
+ grant_ref_t shmem_ref;
+
+} tpmif_t;
+
+void tpmif_disconnect_complete(tpmif_t * tpmif);
+tpmif_t *tpmif_find(domid_t domid, long int instance);
+void tpmif_interface_init(void);
+void tpmif_schedule_work(tpmif_t * tpmif);
+void tpmif_deschedule_work(tpmif_t * tpmif);
+void tpmif_xenbus_init(void);
+int tpmif_map(tpmif_t *tpmif, unsigned long shared_page, unsigned int evtchn);
+irqreturn_t tpmif_be_int(int irq, void *dev_id, struct pt_regs *regs);
+int tpmif_vtpm_open(tpmif_t *tpmif, domid_t domain, u32 instance);
+int tpmif_vtpm_close(u32 instance);
+
+int vtpm_release_packets(tpmif_t * tpmif, int send_msgs);
+
+#define tpmif_get(_b) (atomic_inc(&(_b)->refcnt))
+#define tpmif_put(_b) \
+ do { \
+ if ( atomic_dec_and_test(&(_b)->refcnt) ) \
+ tpmif_disconnect_complete(_b); \
+ } while (0)
+
+
+extern int num_frontends;
+
+#define MMAP_VADDR(t,_req) ((t)->mmap_vstart + ((_req) * PAGE_SIZE))
+
+#endif /* __TPMIF__BACKEND__COMMON_H__ */
diff -r 84ab93e1ee05 -r dd668f7527cb
linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c Thu Sep 1
10:16:14 2005
@@ -0,0 +1,200 @@
+/******************************************************************************
+ * drivers/xen/tpmback/interface.c
+ *
+ * Vritual TPM interface management.
+ *
+ * Copyright (c) 2005, IBM Corporation
+ *
+ * Author: Stefan Berger, stefanb@xxxxxxxxxx
+ *
+ * This code has been derived from drivers/xen/netback/interface.c
+ * Copyright (c) 2004, Keir Fraser
+ */
+
+#include "common.h"
+#include <asm-xen/balloon.h>
+
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+
+#define TPMIF_HASHSZ (2 << 5)
+#define TPMIF_HASH(_d,_h) (((int)(_d)^(int)(_h))&(TPMIF_HASHSZ-1))
+
+static kmem_cache_t *tpmif_cachep;
+int num_frontends = 0;
+LIST_HEAD(tpmif_list);
+
+
+tpmif_t *alloc_tpmif(domid_t domid, long int instance)
+{
+ struct page *page;
+ tpmif_t *tpmif;
+
+ tpmif = kmem_cache_alloc(tpmif_cachep, GFP_KERNEL);
+ if (!tpmif)
+ return ERR_PTR(-ENOMEM);
+
+ memset(tpmif, 0, sizeof(*tpmif));
+ tpmif->domid = domid;
+ tpmif->status = DISCONNECTED;
+ tpmif->tpm_instance = instance;
+ atomic_set(&tpmif->refcnt, 1);
+
+ page = balloon_alloc_empty_page_range(TPMIF_TX_RING_SIZE);
+ BUG_ON(page == NULL);
+ tpmif->mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page));
+
+ list_add(&tpmif->tpmif_list, &tpmif_list);
+ num_frontends++;
+
+ return tpmif;
+}
+
+
+void free_tpmif(tpmif_t *tpmif)
+{
+ num_frontends--;
+ list_del(&tpmif->tpmif_list);
+ kmem_cache_free(tpmif_cachep, tpmif);
+}
+
+
+tpmif_t *tpmif_find(domid_t domid, long int instance)
+{
+ tpmif_t *tpmif;
+
+ list_for_each_entry(tpmif, &tpmif_list, tpmif_list) {
+ if (tpmif->tpm_instance == instance) {
+ if (tpmif->domid == domid) {
+ tpmif_get(tpmif);
+ return tpmif;
+ } else {
+ return NULL;
+ }
+ }
+ }
+
+ return alloc_tpmif(domid, instance);
+}
+
+
+static int map_frontend_page(tpmif_t *tpmif, unsigned long localaddr,
+ unsigned long shared_page)
+{
+ struct gnttab_map_grant_ref op = {
+ .host_addr = localaddr,
+ .flags = GNTMAP_host_map,
+ .ref = shared_page,
+ .dom = tpmif->domid,
+ };
+
+ BUG_ON( HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) );
+
+ if (op.handle < 0) {
+ DPRINTK(" Grant table operation failure !\n");
+ return op.handle;
+ }
+
+ tpmif->shmem_ref = shared_page;
+ tpmif->shmem_handle = op.handle;
+ tpmif->shmem_vaddr = localaddr;
+ return 0;
+}
+
+
+static void unmap_frontend_page(tpmif_t *tpmif)
+{
+ struct gnttab_unmap_grant_ref op;
+
+ op.host_addr = tpmif->shmem_vaddr;
+ op.handle = tpmif->shmem_handle;
+ op.dev_bus_addr = 0;
+
+ BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
+}
+
+
+int tpmif_map(tpmif_t *tpmif,
+ unsigned long shared_page, unsigned int evtchn)
+{
+ struct vm_struct *vma;
+ evtchn_op_t op = { .cmd = EVTCHNOP_bind_interdomain };
+ int err;
+
+ BUG_ON(tpmif->remote_evtchn);
+
+ if ( (vma = get_vm_area(PAGE_SIZE, VM_IOREMAP)) == NULL )
+ return -ENOMEM;
+
+ err = map_frontend_page(tpmif,
+ VMALLOC_VMADDR(vma->addr),
+ shared_page);
+ if (err) {
+ vfree(vma->addr);
+ return err;
+ }
+
+ op.u.bind_interdomain.dom1 = DOMID_SELF;
+ op.u.bind_interdomain.dom2 = tpmif->domid;
+ op.u.bind_interdomain.port1 = 0;
+ op.u.bind_interdomain.port2 = evtchn;
+ err = HYPERVISOR_event_channel_op(&op);
+ if (err) {
+ unmap_frontend_page(tpmif);
+ vfree(vma->addr);
+ return err;
+ }
+
+ tpmif->evtchn = op.u.bind_interdomain.port1;
+ tpmif->remote_evtchn = evtchn;
+
+ tpmif->tx = (tpmif_tx_interface_t *) vma->addr;
+
+ bind_evtchn_to_irqhandler(tpmif->evtchn,
+ tpmif_be_int,
+ 0,
+ "tpmif-backend",
+ tpmif);
+ tpmif->status = CONNECTED;
+ tpmif->shmem_ref = shared_page;
+ tpmif->active = 1;
+
+ return 0;
+}
+
+
+static void __tpmif_disconnect_complete(void *arg)
+{
+ evtchn_op_t op = { .cmd = EVTCHNOP_close };
+ tpmif_t *tpmif = (tpmif_t *) arg;
+
+ op.u.close.port = tpmif->evtchn;
+ op.u.close.dom = DOMID_SELF;
+ HYPERVISOR_event_channel_op(&op);
+ op.u.close.port = tpmif->remote_evtchn;
+ op.u.close.dom = tpmif->domid;
+ HYPERVISOR_event_channel_op(&op);
+
+ if (tpmif->evtchn)
+ unbind_evtchn_from_irqhandler(tpmif->evtchn, tpmif);
+
+ if (tpmif->tx) {
+ unmap_frontend_page(tpmif);
+ vfree(tpmif->tx);
+ }
+
+ free_tpmif(tpmif);
+}
+
+
+void tpmif_disconnect_complete(tpmif_t * tpmif)
+{
+ INIT_WORK(&tpmif->work, __tpmif_disconnect_complete, (void *)tpmif);
+ schedule_work(&tpmif->work);
+}
+
+
+void __init tpmif_interface_init(void)
+{
+ tpmif_cachep = kmem_cache_create("tpmif_cache", sizeof(tpmif_t),
+ 0, 0, NULL, NULL);
+}
diff -r 84ab93e1ee05 -r dd668f7527cb
linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c Thu Sep 1
10:16:14 2005
@@ -0,0 +1,1078 @@
+/******************************************************************************
+ * drivers/xen/tpmback/tpmback.c
+ *
+ * Copyright (c) 2005, IBM Corporation
+ *
+ * Author: Stefan Berger, stefanb@xxxxxxxxxx
+ * Grant table support: Mahadevan Gomathisankaran
+ *
+ * This code has been derived from drivers/xen/netback/netback.c
+ * Copyright (c) 2002-2004, K A Fraser
+ *
+ */
+
+#include "common.h"
+#include <asm-xen/evtchn.h>
+
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/miscdevice.h>
+#include <asm/uaccess.h>
+#include <asm-xen/xenbus.h>
+#include <asm-xen/xen-public/grant_table.h>
+
+
+struct data_exchange {
+ struct list_head pending_pak;
+ struct list_head current_pak;
+ unsigned int copied_so_far;
+ u8 has_opener;
+ rwlock_t pak_lock; // protects all of the previous fields
+ wait_queue_head_t wait_queue;
+};
+
+struct packet {
+ struct list_head next;
+ unsigned int data_len;
+ u8 *data_buffer;
+ tpmif_t *tpmif;
+ u32 tpm_instance;
+ u8 req_tag;
+ u32 last_read;
+ u8 flags;
+ ctrl_msg_t ctrl_msg;
+ struct timer_list processing_timer;
+};
+
+enum {
+ PACKET_FLAG_DISCARD_RESPONSE = 1,
+ PACKET_FLAG_SEND_CONTROLMESSAGE = 2,
+};
+
+static struct data_exchange dataex;
+
+/* local function prototypes */
+static int vtpm_queue_packet(struct packet *pak);
+static int _packet_write(struct packet *pak,
+ const char *data, size_t size,
+ int userbuffer);
+static void processing_timeout(unsigned long ptr);
+static int packet_read_shmem(struct packet *pak,
+ tpmif_t *tpmif,
+ u32 offset,
+ char *buffer,
+ int isuserbuffer,
+ u32 left);
+
+
+#define MAX_PENDING_REQS TPMIF_TX_RING_SIZE
+
+static multicall_entry_t tx_mcl[MAX_PENDING_REQS];
+
+#define MIN(x,y) (x) < (y) ? (x) : (y)
+
+/***************************************************************
+ Packet-related functions
+***************************************************************/
+
+static struct packet *
+packet_find_instance(struct list_head *head, u32 tpm_instance)
+{
+ struct packet *pak;
+ struct list_head *p;
+ /*
+ * traverse the list of packets and return the first
+ * one with the given instance number
+ */
+ list_for_each(p, head) {
+ pak = list_entry(p, struct packet, next);
+ if (pak->tpm_instance == tpm_instance) {
+ return pak;
+ }
+ }
+ return NULL;
+}
+
+static struct packet *
+packet_find_packet(struct list_head *head, void *packet)
+{
+ struct packet *pak;
+ struct list_head *p;
+ /*
+ * traverse the list of packets and return the first
+ * one with the given instance number
+ */
+ list_for_each(p, head) {
+ pak = list_entry(p, struct packet, next);
+ if (pak == packet) {
+ return pak;
+ }
+ }
+ return NULL;
+}
+
+static struct packet *
+packet_alloc(tpmif_t *tpmif, u32 size, u8 req_tag, u8 flags)
+{
+ struct packet *pak = NULL;
+ pak = kmalloc(sizeof(struct packet),
+ GFP_KERNEL);
+ if (NULL != pak) {
+ memset(pak, 0x0, sizeof(*pak));
+ if (tpmif) {
+ pak->tpmif = tpmif;
+ pak->tpm_instance = tpmif->tpm_instance;
+ }
+ pak->data_len = size;
+ pak->req_tag = req_tag;
+ pak->last_read = 0;
+ pak->flags = flags;
+
+ /*
+ * cannot do tpmif_get(tpmif); bad things happen
+ * on the last tpmif_put()
+ */
+ init_timer(&pak->processing_timer);
+ pak->processing_timer.function = processing_timeout;
+ pak->processing_timer.data = (unsigned long)pak;
+ }
+ return pak;
+}
+
+static void inline
+packet_reset(struct packet *pak)
+{
+ pak->last_read = 0;
+}
+
+static void inline
+packet_free(struct packet *pak)
+{
+ del_singleshot_timer_sync(&pak->processing_timer);
+ if (pak->data_buffer) {
+ kfree(pak->data_buffer);
+ }
+ /*
+ * cannot do tpmif_put(pak->tpmif); bad things happen
+ * on the last tpmif_put()
+ */
+ kfree(pak);
+}
+
+static int
+packet_set(struct packet *pak,
+ const unsigned char *buffer, u32 size)
+{
+ int rc = 0;
+ unsigned char *buf = kmalloc(size, GFP_KERNEL);
+ if (NULL != buf) {
+ pak->data_buffer = buf;
+ memcpy(buf, buffer, size);
+ pak->data_len = size;
+ } else {
+ rc = -ENOMEM;
+ }
+ return rc;
+}
+
+
+/*
+ * Write data to the shared memory and send it to the FE.
+ */
+static int
+packet_write(struct packet *pak,
+ const char *data, size_t size,
+ int userbuffer)
+{
+ int rc = 0;
+
+ DPRINTK("Supposed to send %d bytes to front-end!\n",
+ size);
+
+ if (0 != (pak->flags & PACKET_FLAG_SEND_CONTROLMESSAGE)) {
+#ifdef CONFIG_XEN_TPMDEV_CLOSE_IF_VTPM_FAILS
+ u32 res;
+ memcpy(&res, &data[2+4], sizeof(res));
+ if (res != 0) {
+ /*
+ * Will close down this device and have the
+ * FE notified about closure.
+ */
+ }
+#endif
+ }
+
+ if (0 != (pak->flags & PACKET_FLAG_DISCARD_RESPONSE)) {
+ /* Don't send a respone to this packet. Just acknowledge it. */
+ rc = size;
+ } else {
+ rc = _packet_write(pak, data, size, userbuffer);
+ }
+
+ return rc;
+}
+
+
+static int
+_packet_write(struct packet *pak,
+ const char *data, size_t size,
+ int userbuffer)
+{
+ /*
+ * Write into the shared memory pages directly
+ * and send it to the front end.
+ */
+ tpmif_t *tpmif = pak->tpmif;
+ u16 handle;
+ int rc = 0;
+ unsigned int i = 0;
+ unsigned int offset = 0;
+ multicall_entry_t *mcl;
+
+ if (tpmif == NULL)
+ return -EFAULT;
+
+ if (tpmif->status != CONNECTED) {
+ return size;
+ }
+
+ mcl = tx_mcl;
+ while (offset < size && i < TPMIF_TX_RING_SIZE) {
+ unsigned int tocopy;
+ struct gnttab_map_grant_ref map_op;
+ struct gnttab_unmap_grant_ref unmap_op;
+ tpmif_tx_request_t *tx;
+
+ tx = &tpmif->tx->ring[i].req;
+
+ if (0 == tx->addr) {
+ DPRINTK("ERROR: Buffer for outgoing packet NULL?!
i=%d\n", i);
+ return 0;
+ }
+
+ map_op.host_addr = MMAP_VADDR(tpmif, i);
+ map_op.flags = GNTMAP_host_map;
+ map_op.ref = tx->ref;
+ map_op.dom = tpmif->domid;
+
+ if(unlikely(
+ HYPERVISOR_grant_table_op(
+ GNTTABOP_map_grant_ref,
+ &map_op,
+ 1))) {
+ BUG();
+ }
+
+ handle = map_op.handle;
+
+ if (map_op.handle < 0) {
+ DPRINTK(" Grant table operation failure !\n");
+ return 0;
+ }
+ phys_to_machine_mapping[__pa(MMAP_VADDR(tpmif,i)) >>
+ PAGE_SHIFT] =
+ FOREIGN_FRAME(map_op.dev_bus_addr >> PAGE_SHIFT);
+
+ tocopy = size - offset;
+ if (tocopy > PAGE_SIZE) {
+ tocopy = PAGE_SIZE;
+ }
+ if (userbuffer) {
+ if (copy_from_user((void *)(MMAP_VADDR(tpmif,i) |
+ (tx->addr & ~PAGE_MASK)),
+ (void __user *)&data[offset],
+ tocopy)) {
+ tpmif_put(tpmif);
+ return -EFAULT;
+ }
+ } else {
+ memcpy((void *)(MMAP_VADDR(tpmif,i) |
+ (tx->addr & ~PAGE_MASK)),
+ &data[offset], tocopy);
+ }
+ tx->size = tocopy;
+
+ unmap_op.host_addr = MMAP_VADDR(tpmif, i);
+ unmap_op.handle = handle;
+ unmap_op.dev_bus_addr = 0;
+
+ if(unlikely(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,
+ &unmap_op,
+ 1))) {
+ BUG();
+ }
+
+ offset += tocopy;
+ i++;
+ }
+
+ rc = offset;
+ DPRINTK("Notifying frontend via event channel %d\n",
+ tpmif->evtchn);
+ notify_via_evtchn(tpmif->evtchn);
+
+ return rc;
+}
+
+/*
+ * Read data from the shared memory and copy it directly into the
+ * provided buffer. Advance the read_last indicator which tells
+ * how many bytes have already been read.
+ */
+static int
+packet_read(struct packet *pak, size_t numbytes,
+ char *buffer, size_t buffersize,
+ int userbuffer)
+{
+ tpmif_t *tpmif = pak->tpmif;
+ /*
+ * I am supposed to read 'numbytes' of data from the
+ * buffer.
+ * The first 4 bytes that are read are the instance number in
+ * network byte order, after that comes the data from the
+ * shared memory buffer.
+ */
+ u32 to_copy;
+ u32 offset = 0;
+ u32 room_left = buffersize;
+ /*
+ * Ensure that we see the request when we copy it.
+ */
+ mb();
+
+ if (pak->last_read < 4) {
+ /*
+ * copy the instance number into the buffer
+ */
+ u32 instance_no = htonl(pak->tpm_instance);
+ u32 last_read = pak->last_read;
+ to_copy = MIN(4 - last_read, numbytes);
+
+ if (userbuffer) {
+ if (copy_to_user(&buffer[0],
+ &(((u8 *)&instance_no)[last_read]),
+ to_copy)) {
+ return -EFAULT;
+ }
+ } else {
+ memcpy(&buffer[0],
+ &(((u8 *)&instance_no)[last_read]),
+ to_copy);
+ }
+
+ pak->last_read += to_copy;
+ offset += to_copy;
+ room_left -= to_copy;
+ }
+
+ /*
+ * If the packet has a data buffer appended, read from it...
+ */
+
+ if (room_left > 0) {
+ if (pak->data_buffer) {
+ u32 to_copy = MIN(pak->data_len - offset, room_left);
+ u32 last_read = pak->last_read - 4;
+ if (userbuffer) {
+ if (copy_to_user(&buffer[offset],
+ &pak->data_buffer[last_read],
+ to_copy)) {
+ return -EFAULT;
+ }
+ } else {
+ memcpy(&buffer[offset],
+ &pak->data_buffer[last_read],
+ to_copy);
+ }
+ pak->last_read += to_copy;
+ offset += to_copy;
+ } else {
+ offset = packet_read_shmem(pak,
+ tpmif,
+ offset,
+ buffer,
+ userbuffer,
+ room_left);
+ }
+ }
+ return offset;
+}
+
+
+static int
+packet_read_shmem(struct packet *pak,
+ tpmif_t *tpmif,
+ u32 offset,
+ char *buffer,
+ int isuserbuffer,
+ u32 room_left) {
+ u32 last_read = pak->last_read - 4;
+ u32 i = (last_read / PAGE_SIZE);
+ u32 pg_offset = last_read & (PAGE_SIZE - 1);
+ u32 to_copy;
+ u16 handle;
+
+ tpmif_tx_request_t *tx;
+ tx = &tpmif->tx->ring[0].req;
+ /*
+ * Start copying data at the page with index 'index'
+ * and within that page at offset 'offset'.
+ * Copy a maximum of 'room_left' bytes.
+ */
+ to_copy = MIN(PAGE_SIZE - pg_offset, room_left);
+ while (to_copy > 0) {
+ void *src;
+ struct gnttab_map_grant_ref map_op;
+ struct gnttab_unmap_grant_ref unmap_op;
+
+ tx = &tpmif->tx->ring[i].req;
+
+ map_op.host_addr = MMAP_VADDR(tpmif, i);
+ map_op.flags = GNTMAP_host_map;
+ map_op.ref = tx->ref;
+ map_op.dom = tpmif->domid;
+
+ if(unlikely(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref,
+ &map_op,
+ 1))) {
+ BUG();
+ }
+
+ if (map_op.handle < 0) {
+ DPRINTK(" Grant table operation failure !\n");
+ return -EFAULT;
+ }
+
+ handle = map_op.handle;
+
+ if (to_copy > tx->size) {
+ /*
+ * This is the case when the user wants to read more
+ * than what we have. So we just give him what we
+ * have.
+ */
+ to_copy = MIN(tx->size, to_copy);
+ }
+
+ DPRINTK("Copying from mapped memory at %08lx\n",
+ (unsigned long)(MMAP_VADDR(tpmif,i) |
+ (tx->addr & ~PAGE_MASK)));
+
+ src = (void *)(MMAP_VADDR(tpmif,i) | ((tx->addr & ~PAGE_MASK) +
pg_offset));
+ if (isuserbuffer) {
+ if (copy_to_user(&buffer[offset],
+ src,
+ to_copy)) {
+ return -EFAULT;
+ }
+ } else {
+ memcpy(&buffer[offset],
+ src,
+ to_copy);
+ }
+
+
+ DPRINTK("Data from TPM-FE of domain %d are %d %d %d %d\n",
+ tpmif->domid, buffer[offset],
buffer[offset+1],buffer[offset+2],buffer[offset+3]);
+
+ unmap_op.host_addr = MMAP_VADDR(tpmif, i);
+ unmap_op.handle = handle;
+ unmap_op.dev_bus_addr = 0;
+
+ if(unlikely(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,
+ &unmap_op,
+ 1))) {
+ BUG();
+ }
+
+ offset += to_copy;
+ pg_offset = 0;
+ last_read += to_copy;
+ room_left -= to_copy;
+
+ to_copy = MIN(PAGE_SIZE, room_left);
+ i++;
+ } /* while (to_copy > 0) */
+ /*
+ * Adjust the last_read pointer
+ */
+ pak->last_read = last_read + 4;
+ return offset;
+}
+
+
+/* ============================================================
+ * The file layer for reading data from this device
+ * ============================================================
+ */
+static int
+vtpm_op_open(struct inode *inode, struct file *f)
+{
+ int rc = 0;
+ unsigned long flags;
+
+ write_lock_irqsave(&dataex.pak_lock, flags);
+ if (dataex.has_opener == 0) {
+ dataex.has_opener = 1;
+ } else {
+ rc = -EPERM;
+ }
+ write_unlock_irqrestore(&dataex.pak_lock, flags);
+ return rc;
+}
+
+static ssize_t
+vtpm_op_read(struct file *file,
+ char __user * data, size_t size, loff_t * offset)
+{
+ int ret_size = -ENODATA;
+ struct packet *pak = NULL;
+ unsigned long flags;
+
+ write_lock_irqsave(&dataex.pak_lock, flags);
+
+ if (list_empty(&dataex.pending_pak)) {
+ write_unlock_irqrestore(&dataex.pak_lock, flags);
+ wait_event_interruptible(dataex.wait_queue,
+ !list_empty(&dataex.pending_pak));
+ write_lock_irqsave(&dataex.pak_lock, flags);
+ }
+
+ if (!list_empty(&dataex.pending_pak)) {
+ unsigned int left;
+ pak = list_entry(dataex.pending_pak.next, struct packet, next);
+
+ left = pak->data_len - dataex.copied_so_far;
+
+ DPRINTK("size given by app: %d, available: %d\n", size, left);
+
+ ret_size = MIN(size,left);
+
+ ret_size = packet_read(pak, ret_size, data, size, 1);
+ if (ret_size < 0) {
+ ret_size = -EFAULT;
+ } else {
+ DPRINTK("Copied %d bytes to user buffer\n", ret_size);
+
+ dataex.copied_so_far += ret_size;
+ if (dataex.copied_so_far >= pak->data_len + 4) {
+ DPRINTK("All data from this packet given to
app.\n");
+ /* All data given to app */
+
+
del_singleshot_timer_sync(&pak->processing_timer);
+ list_del(&pak->next);
+ list_add_tail(&pak->next, &dataex.current_pak);
+ /*
+ * The more fontends that are handled at the
same time,
+ * the more time we give the TPM to process the
request.
+ */
+ mod_timer(&pak->processing_timer,
+ jiffies + (num_frontends * 10 * HZ));
+ dataex.copied_so_far = 0;
+ }
+ }
+ }
+ write_unlock_irqrestore(&dataex.pak_lock, flags);
+
+ DPRINTK("Returning result from read to app: %d\n", ret_size);
+
+ return ret_size;
+}
+
+/*
+ * Write operation - only works after a previous read operation!
+ */
+static ssize_t
+vtpm_op_write(struct file *file, const char __user * data, size_t size,
+ loff_t * offset)
+{
+ struct packet *pak;
+ int rc = 0;
+ unsigned int off = 4;
+ unsigned long flags;
+ u32 instance_no = 0;
+ u32 len_no = 0;
+
+ /*
+ * Minimum required packet size is:
+ * 4 bytes for instance number
+ * 2 bytes for tag
+ * 4 bytes for paramSize
+ * 4 bytes for the ordinal
+ * sum: 14 bytes
+ */
+ if ( size < off + 10 ) {
+ return -EFAULT;
+ }
+
+ if (copy_from_user(&instance_no,
+ (void __user *)&data[0],
+ 4)) {
+ return -EFAULT;
+ }
+
+ if (copy_from_user(&len_no,
+ (void __user *)&data[off+2],
+ 4) ||
+ (off + ntohl(len_no) != size)) {
+ return -EFAULT;
+ }
+
+ write_lock_irqsave(&dataex.pak_lock, flags);
+ pak = packet_find_instance(&dataex.current_pak, ntohl(instance_no));
+
+ if (pak == NULL) {
+ write_unlock_irqrestore(&dataex.pak_lock, flags);
+ printk(KERN_ALERT "No associated packet!\n");
+ return -EFAULT;
+ } else {
+ del_singleshot_timer_sync(&pak->processing_timer);
+ list_del(&pak->next);
+ }
+
+ write_unlock_irqrestore(&dataex.pak_lock, flags);
+
+ /*
+ * The first 'offset' bytes must be the instance number.
+ * I will just pull that from the packet.
+ */
+ size -= off;
+ data = &data[off];
+
+ rc = packet_write(pak, data, size, 1);
+
+ if (rc > 0) {
+ /* I neglected the first 4 bytes */
+ rc += off;
+ }
+ packet_free(pak);
+ return rc;
+}
+
+static int
+vtpm_op_release(struct inode *inode, struct file *file)
+{
+ unsigned long flags;
+ vtpm_release_packets(NULL, 1);
+ write_lock_irqsave(&dataex.pak_lock, flags);
+ dataex.has_opener = 0;
+ write_unlock_irqrestore(&dataex.pak_lock, flags);
+ return 0;
+}
+
+static unsigned int
+vtpm_op_poll(struct file *file, struct poll_table_struct *pst)
+{
+ return 0;
+}
+
+static struct file_operations vtpm_ops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .open = vtpm_op_open,
+ .read = vtpm_op_read,
+ .write = vtpm_op_write,
+ .release = vtpm_op_release,
+ .poll = vtpm_op_poll,
+};
+
+static struct miscdevice ibmvtpms_miscdevice = {
+ .minor = 225,
+ .name = "vtpm",
+ .fops = &vtpm_ops,
+};
+
+
+/***************************************************************
+ Virtual TPM functions and data stuctures
+***************************************************************/
+
+static u8 create_cmd[] = {
+ 1,193, /* 0: TPM_TAG_RQU_COMMAMD */
+ 0,0,0,19, /* 2: length */
+ 0,0,0,0x1, /* 6: VTPM_ORD_OPEN */
+ 0, /* 10: VTPM type */
+ 0,0,0,0, /* 11: domain id */
+ 0,0,0,0 /* 15: instance id */
+};
+
+static u8 destroy_cmd[] = {
+ 1,193, /* 0: TPM_TAG_RQU_COMMAMD */
+ 0,0,0,14, /* 2: length */
+ 0,0,0,0x2, /* 6: VTPM_ORD_CLOSE */
+ 0,0,0,0 /* 10: instance id */
+};
+
+int tpmif_vtpm_open(tpmif_t *tpmif, domid_t domid, u32 instance)
+{
+ int rc = 0;
+ struct packet *pak = packet_alloc(tpmif, sizeof(create_cmd),
create_cmd[0],
+ PACKET_FLAG_DISCARD_RESPONSE|
+ PACKET_FLAG_SEND_CONTROLMESSAGE);
+ if (pak) {
+ u8 buf[sizeof(create_cmd)];
+ u32 domid_no = htonl((u32)domid);
+ u32 instance_no = htonl(instance);
+ memcpy(buf, create_cmd, sizeof(create_cmd));
+
+ memcpy(&buf[11], &domid_no, sizeof(u32));
+ memcpy(&buf[15], &instance_no, sizeof(u32));
+
+ /* copy the buffer into the packet */
+ rc = packet_set(pak, buf, sizeof(buf));
+
+ if (rc == 0) {
+ pak->tpm_instance = 0;
+ rc = vtpm_queue_packet(pak);
+ }
+ if (rc < 0) {
+ /* could not be queued or built */
+ packet_free(pak);
+ }
+ } else {
+ rc = -ENOMEM;
+ }
+ return rc;
+}
+
+int tpmif_vtpm_close(u32 instid)
+{
+ int rc = 0;
+ struct packet *pak;
+
+ pak = packet_alloc(NULL,
+ sizeof(create_cmd),
+ create_cmd[0],
+ PACKET_FLAG_DISCARD_RESPONSE|
+ PACKET_FLAG_SEND_CONTROLMESSAGE);
+ if (pak) {
+ u8 buf[sizeof(destroy_cmd)];
+ u32 instid_no = htonl(instid);
+ memcpy(buf, destroy_cmd, sizeof(destroy_cmd));
+ memcpy(&buf[10], &instid_no, sizeof(u32));
+
+ /* copy the buffer into the packet */
+ rc = packet_set(pak, buf, sizeof(buf));
+
+ if (rc == 0) {
+ pak->tpm_instance = 0;
+ rc = vtpm_queue_packet(pak);
+ }
+ if (rc < 0) {
+ /* could not be queued or built */
+ packet_free(pak);
+ }
+ } else {
+ rc = -ENOMEM;
+ }
+ return rc;
+}
+
+
+/***************************************************************
+ Utility functions
+***************************************************************/
+
+static int
+tpm_send_fail_message(struct packet *pak, u8 req_tag)
+{
+ int rc;
+ static const unsigned char tpm_error_message_fail[] = {
+ 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0a,
+ 0x00, 0x00, 0x00, 0x09 /* TPM_FAIL */
+ };
+ unsigned char buffer[sizeof(tpm_error_message_fail)];
+
+ memcpy(buffer, tpm_error_message_fail, sizeof(tpm_error_message_fail));
+ /*
+ * Insert the right response tag depending on the given tag
+ * All response tags are '+3' to the request tag.
+ */
+ buffer[1] = req_tag + 3;
+
+ /*
+ * Write the data to shared memory and notify the front-end
+ */
+ rc = packet_write(pak, buffer, sizeof(buffer), 0);
+
+ return rc;
+}
+
+
+static void
+_vtpm_release_packets(struct list_head *head, tpmif_t *tpmif,
+ int send_msgs)
+{
+ struct packet *pak;
+ struct list_head *pos, *tmp;
+
+ list_for_each_safe(pos, tmp, head) {
+ pak = list_entry(pos, struct packet, next);
+ if (tpmif == NULL || pak->tpmif == tpmif) {
+ int can_send = 0;
+ del_singleshot_timer_sync(&pak->processing_timer);
+ list_del(&pak->next);
+
+ if (pak->tpmif && pak->tpmif->status == CONNECTED) {
+ can_send = 1;
+ }
+
+ if (send_msgs && can_send) {
+ tpm_send_fail_message(pak, pak->req_tag);
+ }
+ packet_free(pak);
+ }
+ }
+}
+
+
+int
+vtpm_release_packets(tpmif_t *tpmif, int send_msgs)
+{
+ unsigned long flags;
+
+ write_lock_irqsave(&dataex.pak_lock, flags);
+
+ _vtpm_release_packets(&dataex.pending_pak, tpmif, send_msgs);
+ _vtpm_release_packets(&dataex.current_pak, tpmif, send_msgs);
+
+ write_unlock_irqrestore(&dataex.pak_lock,
+ flags);
+ return 0;
+}
+
+
+static int vtpm_queue_packet(struct packet *pak)
+{
+ int rc = 0;
+ if (dataex.has_opener) {
+ unsigned long flags;
+ write_lock_irqsave(&dataex.pak_lock, flags);
+ list_add_tail(&pak->next, &dataex.pending_pak);
+ /* give the TPM some time to pick up the request */
+ mod_timer(&pak->processing_timer, jiffies + (10 * HZ));
+ write_unlock_irqrestore(&dataex.pak_lock,
+ flags);
+
+ wake_up_interruptible(&dataex.wait_queue);
+ } else {
+ rc = -EFAULT;
+ }
+ return rc;
+}
+
+
+static int vtpm_receive(tpmif_t *tpmif, u32 size)
+{
+ int rc = 0;
+ unsigned char buffer[10];
+ __be32 *native_size;
+
+ struct packet *pak = packet_alloc(tpmif, size, buffer[4], 0);
+ if (NULL == pak) {
+ return -ENOMEM;
+ }
+ /*
+ * Read 10 bytes from the received buffer to test its
+ * content for validity.
+ */
+ if (sizeof(buffer) != packet_read(pak,
+ sizeof(buffer), buffer,
+ sizeof(buffer), 0)) {
+ goto failexit;
+ }
+ /*
+ * Reset the packet read pointer so we can read all its
+ * contents again.
+ */
+ packet_reset(pak);
+
+ native_size = (__force __be32 *)(&buffer[4+2]);
+ /*
+ * Verify that the size of the packet is correct
+ * as indicated and that there's actually someone reading packets.
+ * The minimum size of the packet is '10' for tag, size indicator
+ * and ordinal.
+ */
+ if (size < 10 ||
+ be32_to_cpu(*native_size) != size ||
+ 0 == dataex.has_opener) {
+ rc = -EINVAL;
+ goto failexit;
+ } else {
+ if ((rc = vtpm_queue_packet(pak)) < 0) {
+ goto failexit;
+ }
+ }
+ return 0;
+
+failexit:
+ if (pak) {
+ tpm_send_fail_message(pak, buffer[4+1]);
+ packet_free(pak);
+ }
+ return rc;
+}
+
+
+/*
+ * Timeout function that gets invoked when a packet has not been processed
+ * during the timeout period.
+ * The packet must be on a list when this function is invoked. This
+ * also means that once its taken off a list, the timer must be
+ * destroyed as well.
+ */
+static void processing_timeout(unsigned long ptr)
+{
+ struct packet *pak = (struct packet *)ptr;
+ unsigned long flags;
+ write_lock_irqsave(&dataex.pak_lock, flags);
+ /*
+ * The packet needs to be searched whether it
+ * is still on the list.
+ */
+ if (pak == packet_find_packet(&dataex.pending_pak, pak) ||
+ pak == packet_find_packet(&dataex.current_pak, pak) ) {
+ list_del(&pak->next);
+ tpm_send_fail_message(pak, pak->req_tag);
+ packet_free(pak);
+ }
+
+ write_unlock_irqrestore(&dataex.pak_lock, flags);
+}
+
+
+
+static void tpm_tx_action(unsigned long unused);
+static DECLARE_TASKLET(tpm_tx_tasklet, tpm_tx_action, 0);
+
+#define MAX_PENDING_REQS TPMIF_TX_RING_SIZE
+
+static struct list_head tpm_schedule_list;
+static spinlock_t tpm_schedule_list_lock;
+
+static inline void
+maybe_schedule_tx_action(void)
+{
+ smp_mb();
+ tasklet_schedule(&tpm_tx_tasklet);
+}
+
+static inline int
+__on_tpm_schedule_list(tpmif_t * tpmif)
+{
+ return tpmif->list.next != NULL;
+}
+
+static void
+remove_from_tpm_schedule_list(tpmif_t * tpmif)
+{
+ spin_lock_irq(&tpm_schedule_list_lock);
+ if (likely(__on_tpm_schedule_list(tpmif))) {
+ list_del(&tpmif->list);
+ tpmif->list.next = NULL;
+ tpmif_put(tpmif);
+ }
+ spin_unlock_irq(&tpm_schedule_list_lock);
+}
+
+static void
+add_to_tpm_schedule_list_tail(tpmif_t * tpmif)
+{
+ if (__on_tpm_schedule_list(tpmif))
+ return;
+
+ spin_lock_irq(&tpm_schedule_list_lock);
+ if (!__on_tpm_schedule_list(tpmif) && tpmif->active) {
+ list_add_tail(&tpmif->list, &tpm_schedule_list);
+ tpmif_get(tpmif);
+ }
+ spin_unlock_irq(&tpm_schedule_list_lock);
+}
+
+void
+tpmif_schedule_work(tpmif_t * tpmif)
+{
+ add_to_tpm_schedule_list_tail(tpmif);
+ maybe_schedule_tx_action();
+}
+
+void
+tpmif_deschedule_work(tpmif_t * tpmif)
+{
+ remove_from_tpm_schedule_list(tpmif);
+}
+
+
+static void
+tpm_tx_action(unsigned long unused)
+{
+ struct list_head *ent;
+ tpmif_t *tpmif;
+ tpmif_tx_request_t *tx;
+
+ DPRINTK("%s: Getting data from front-end(s)!\n", __FUNCTION__);
+
+ while (!list_empty(&tpm_schedule_list)) {
+ /* Get a tpmif from the list with work to do. */
+ ent = tpm_schedule_list.next;
+ tpmif = list_entry(ent, tpmif_t, list);
+ tpmif_get(tpmif);
+ remove_from_tpm_schedule_list(tpmif);
+ /*
+ * Ensure that we see the request when we read from it.
+ */
+ mb();
+
+ tx = &tpmif->tx->ring[0].req;
+
+ /* pass it up */
+ vtpm_receive(tpmif, tx->size);
+
+ tpmif_put(tpmif);
+ }
+}
+
+irqreturn_t
+tpmif_be_int(int irq, void *dev_id, struct pt_regs *regs)
+{
+ tpmif_t *tpmif = dev_id;
+ add_to_tpm_schedule_list_tail(tpmif);
+ maybe_schedule_tx_action();
+ return IRQ_HANDLED;
+}
+
+static int __init
+tpmback_init(void)
+{
+ int rc;
+ if (!(xen_start_info.flags & SIF_TPM_BE_DOMAIN) &&
+ !(xen_start_info.flags & SIF_INITDOMAIN)) {
+ printk(KERN_ALERT "Neither TPM-BE Domain nor INIT domain!\n");
+ return 0;
+ }
+
+ if ((rc = misc_register(&ibmvtpms_miscdevice)) != 0) {
+ printk(KERN_ALERT "Could not register misc device for TPM
BE.\n");
+ return rc;
+ }
+
+ INIT_LIST_HEAD(&dataex.pending_pak);
+ INIT_LIST_HEAD(&dataex.current_pak);
+ dataex.has_opener = 0;
+ rwlock_init(&dataex.pak_lock);
+ init_waitqueue_head(&dataex.wait_queue);
+
+ spin_lock_init(&tpm_schedule_list_lock);
+ INIT_LIST_HEAD(&tpm_schedule_list);
+
+ tpmif_interface_init();
+ tpmif_xenbus_init();
+
+ printk(KERN_ALERT "Successfully initialized TPM backend driver.\n");
+
+ return 0;
+}
+
+__initcall(tpmback_init);
diff -r 84ab93e1ee05 -r dd668f7527cb
linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c Thu Sep 1 10:16:14 2005
@@ -0,0 +1,271 @@
+/* Xenbus code for tpmif backend
+ Copyright (C) 2005 Rusty Russell <rusty@xxxxxxxxxxxxxxx>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+#include <stdarg.h>
+#include <linux/module.h>
+#include <asm-xen/xenbus.h>
+#include "common.h"
+
+struct backend_info
+{
+ struct xenbus_device *dev;
+
+ /* our communications channel */
+ tpmif_t *tpmif;
+
+ long int frontend_id;
+ long int instance; // instance of TPM
+
+ /* watch front end for changes */
+ struct xenbus_watch backend_watch;
+
+ struct xenbus_watch watch;
+ char * frontpath;
+};
+
+static int tpmback_remove(struct xenbus_device *dev)
+{
+ struct backend_info *be = dev->data;
+
+ if (be->watch.node) {
+ unregister_xenbus_watch(&be->watch);
+ }
+ unregister_xenbus_watch(&be->backend_watch);
+
+ tpmif_vtpm_close(be->instance);
+
+ if (be->tpmif) {
+ tpmif_put(be->tpmif);
+ }
+
+ if (be->frontpath)
+ kfree(be->frontpath);
+ kfree(be);
+ return 0;
+}
+
+
+static void frontend_changed(struct xenbus_watch *watch, const char *node)
+{
+ unsigned long ringref;
+ unsigned int evtchn;
+ unsigned long ready = 1;
+ int err;
+ struct backend_info *be
+ = container_of(watch, struct backend_info, watch);
+
+ /* If other end is gone, delete ourself. */
+ if (node && !xenbus_exists(be->frontpath, "")) {
+ xenbus_rm(be->dev->nodename, "");
+ device_unregister(&be->dev->dev);
+ return;
+ }
+
+ if (be->tpmif == NULL || be->tpmif->status == CONNECTED)
+ return;
+
+ err = xenbus_gather(be->frontpath,
+ "ring-ref", "%lu", &ringref,
+ "event-channel", "%u", &evtchn, NULL);
+ if (err) {
+ xenbus_dev_error(be->dev, err,
+ "reading %s/grant-id and event-channel",
+ be->frontpath);
+ return;
+ }
+
+
+ /*
+ * Tell the front-end that we are ready to go -
+ * unless something bad happens
+ */
+ err = xenbus_transaction_start(be->dev->nodename);
+ if (err) {
+ xenbus_dev_error(be->dev, err, "starting transaction");
+ return;
+ }
+
+ err = xenbus_printf(be->dev->nodename,
+ "ready", "%lu", ready);
+ if (err) {
+ xenbus_dev_error(be->dev, err, "writing 'ready'");
+ goto abort;
+ }
+
+ err = tpmif_map(be->tpmif, ringref, evtchn);
+ if (err) {
+ xenbus_dev_error(be->dev, err,
+ "mapping shared-frame %lu port %u",
+ ringref, evtchn);
+ goto abort;
+ }
+
+ err = tpmif_vtpm_open(be->tpmif,
+ be->frontend_id,
+ be->instance);
+ if (err) {
+ xenbus_dev_error(be->dev, err,
+ "queueing vtpm open packet");
+ /*
+ * Should close down this device and notify FE
+ * about closure.
+ */
+ goto abort;
+ }
+
+ xenbus_transaction_end(0);
+ xenbus_dev_ok(be->dev);
+ return;
+abort:
+ xenbus_transaction_end(1);
+}
+
+
+static void backend_changed(struct xenbus_watch *watch, const char *node)
+{
+ int err;
+ long int instance;
+ struct backend_info *be
+ = container_of(watch, struct backend_info, backend_watch);
+ struct xenbus_device *dev = be->dev;
+
+ err = xenbus_scanf(dev->nodename, "instance", "%li", &instance);
+ if (XENBUS_EXIST_ERR(err))
+ return;
+ if (err < 0) {
+ xenbus_dev_error(dev, err, "reading 'instance' variable");
+ return;
+ }
+
+ if (be->instance != -1 && be->instance != instance) {
+ printk(KERN_WARNING
+ "cannot change the instance\n");
+ return;
+ }
+ be->instance = instance;
+
+ if (be->tpmif == NULL) {
+ be->tpmif = tpmif_find(be->frontend_id,
+ instance);
+ if (IS_ERR(be->tpmif)) {
+ err = PTR_ERR(be->tpmif);
+ be->tpmif = NULL;
+ xenbus_dev_error(dev, err, "creating interface");
+ return;
+ }
+
+ /* Pass in NULL node to skip exist test. */
+ frontend_changed(&be->watch, be->frontpath);
+ }
+}
+
+
+static int tpmback_probe(struct xenbus_device *dev,
+ const struct xenbus_device_id *id)
+{
+ struct backend_info *be;
+ char *frontend;
+ int err;
+
+ be = kmalloc(sizeof(*be), GFP_KERNEL);
+ if (!be) {
+ xenbus_dev_error(dev, -ENOMEM, "allocating backend structure");
+ err = -ENOMEM;
+ }
+
+ memset(be, 0, sizeof(*be));
+
+ frontend = NULL;
+ err = xenbus_gather(dev->nodename,
+ "frontend-id", "%li", &be->frontend_id,
+ "frontend", NULL, &frontend,
+ NULL);
+ if (XENBUS_EXIST_ERR(err))
+ goto free_be;
+ if (err < 0) {
+ xenbus_dev_error(dev, err,
+ "reading %s/frontend or frontend-id",
+ dev->nodename);
+ goto free_be;
+ }
+ if (strlen(frontend) == 0 || !xenbus_exists(frontend, "")) {
+ /* If we can't get a frontend path and a frontend-id,
+ * then our bus-id is no longer valid and we need to
+ * destroy the backend device.
+ */
+ err = -ENOENT;
+ goto free_be;
+ }
+
+ be->dev = dev;
+ be->backend_watch.node = dev->nodename;
+ be->backend_watch.callback = backend_changed;
+ be->instance = -1;
+ err = register_xenbus_watch(&be->backend_watch);
+ if (err) {
+ be->backend_watch.node = NULL;
+ xenbus_dev_error(dev, err, "adding backend watch on %s",
+ dev->nodename);
+ goto free_be;
+ }
+
+ be->frontpath = frontend;
+ be->watch.node = be->frontpath;
+ be->watch.callback = frontend_changed;
+ err = register_xenbus_watch(&be->watch);
+ if (err) {
+ be->watch.node = NULL;
+ xenbus_dev_error(dev, err,
+ "adding frontend watch on %s",
+ be->frontpath);
+ goto free_be;
+ }
+
+ dev->data = be;
+
+ backend_changed(&be->backend_watch, dev->nodename);
+ return err;
+
+free_be:
+ if (be->backend_watch.node)
+ unregister_xenbus_watch(&be->backend_watch);
+ if (frontend)
+ kfree(frontend);
+ kfree(be);
+ return err;
+}
+
+
+static struct xenbus_device_id tpmback_ids[] = {
+ { "vtpm" },
+ { "" }
+};
+
+
+static struct xenbus_driver tpmback = {
+ .name = "vtpm",
+ .owner = THIS_MODULE,
+ .ids = tpmback_ids,
+ .probe = tpmback_probe,
+ .remove = tpmback_remove,
+};
+
+
+void tpmif_xenbus_init(void)
+{
+ xenbus_register_backend(&tpmback);
+}
diff -r 84ab93e1ee05 -r dd668f7527cb
linux-2.6-xen-sparse/drivers/xen/tpmfront/Makefile
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/Makefile Thu Sep 1
10:16:14 2005
@@ -0,0 +1,2 @@
+
+obj-$(CONFIG_XEN_TPMDEV_FRONTEND) += tpmfront.o
diff -r 84ab93e1ee05 -r dd668f7527cb
linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c Thu Sep 1
10:16:14 2005
@@ -0,0 +1,739 @@
+/*
+ * Copyright (c) 2005, IBM Corporation
+ *
+ * Author: Stefan Berger, stefanb@xxxxxxxxxx
+ * Grant table support: Mahadevan Gomathisankaran
+ *
+ * This code has been derived from drivers/xen/netfront/netfront.c
+ *
+ * Copyright (c) 2002-2004, K A Fraser
+ *
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/tpmfe.h>
+
+#include <asm/semaphore.h>
+#include <asm/io.h>
+#include <asm-xen/evtchn.h>
+#include <asm-xen/ctrl_if.h>
+#include <asm-xen/xen-public/io/tpmif.h>
+#include <asm/uaccess.h>
+#include <asm-xen/xenbus.h>
+#include <asm-xen/xen-public/io/domain_controller.h>
+#include <asm-xen/xen-public/grant_table.h>
+
+#include "tpmfront.h"
+
+#undef DEBUG
+
+#if 1
+#define ASSERT(_p) \
+ if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , \
+ __LINE__, __FILE__); *(int*)0=0; }
+#else
+#define ASSERT(_p)
+#endif
+
+/* locally visible variables */
+static grant_ref_t gref_head;
+static struct tpm_private my_private;
+
+/* local function prototypes */
+static irqreturn_t tpmif_int(int irq,
+ void *tpm_priv,
+ struct pt_regs *ptregs);
+static void tpmif_rx_action(unsigned long unused);
+static void tpmif_connect(u16 evtchn, domid_t domid);
+static DECLARE_TASKLET(tpmif_rx_tasklet, tpmif_rx_action, 0);
+static int tpm_allocate_buffers(struct tpm_private *tp);
+static void tpmif_set_connected_state(struct tpm_private *tp, int newstate);
+static int tpm_xmit(struct tpm_private *tp,
+ const u8 * buf, size_t count, int userbuffer,
+ void *remember);
+
+#if DEBUG
+#define DPRINTK(fmt, args...) \
+ printk(KERN_ALERT "xen_tpm_fr (%s:%d) " fmt, __FUNCTION__, __LINE__,
##args)
+#else
+#define DPRINTK(fmt, args...) ((void)0)
+#endif
+#define IPRINTK(fmt, args...) \
+ printk(KERN_INFO "xen_tpm_fr: " fmt, ##args)
+#define WPRINTK(fmt, args...) \
+ printk(KERN_WARNING "xen_tpm_fr: " fmt, ##args)
+
+
+static inline int
+tx_buffer_copy(struct tx_buffer *txb, const u8 * src, int len,
+ int isuserbuffer)
+{
+ int copied = len;
+
+ if (len > txb->size) {
+ copied = txb->size;
+ }
+ if (isuserbuffer) {
+ if (copy_from_user(txb->data,
+ src,
+ copied)) {
+ return -EFAULT;
+ }
+ } else {
+ memcpy(txb->data, src, copied);
+ }
+ txb->len = len;
+ return copied;
+}
+
+static inline struct tx_buffer *tx_buffer_alloc(void)
+{
+ struct tx_buffer *txb = kmalloc(sizeof (struct tx_buffer),
+ GFP_KERNEL);
+
+ if (txb) {
+ txb->len = 0;
+ txb->size = PAGE_SIZE;
+ txb->data = (unsigned char *)__get_free_page(GFP_KERNEL);
+ if (txb->data == NULL) {
+ kfree(txb);
+ txb = NULL;
+ }
+ }
+ return txb;
+}
+
+
+/**************************************************************
+
+ The interface to let the tpm plugin register its callback
+ function and send data to another partition using this module
+
+**************************************************************/
+
+static DECLARE_MUTEX(upperlayer_lock);
+static DECLARE_MUTEX(suspend_lock);
+static struct tpmfe_device *upperlayer_tpmfe;
+
+/*
+ * Send data via this module by calling this function
+ */
+int tpm_fe_send(const u8 * buf, size_t count, void *ptr)
+{
+ int sent = 0;
+ struct tpm_private *tp = &my_private;
+
+ down(&suspend_lock);
+ sent = tpm_xmit(tp, buf, count, 0, ptr);
+ up(&suspend_lock);
+
+ return sent;
+}
+EXPORT_SYMBOL(tpm_fe_send);
+
+/*
+ * Register a callback for receiving data from this module
+ */
+int tpm_fe_register_receiver(struct tpmfe_device *tpmfe_dev)
+{
+ int rc = 0;
+
+ down(&upperlayer_lock);
+ if (NULL == upperlayer_tpmfe) {
+ upperlayer_tpmfe = tpmfe_dev;
+ tpmfe_dev->max_tx_size = TPMIF_TX_RING_SIZE * PAGE_SIZE;
+ } else {
+ rc = -EBUSY;
+ }
+ up(&upperlayer_lock);
+ return rc;
+}
+EXPORT_SYMBOL(tpm_fe_register_receiver);
+
+/*
+ * Unregister the callback for receiving data from this module
+ */
+void tpm_fe_unregister_receiver(void)
+{
+ down(&upperlayer_lock);
+ upperlayer_tpmfe = NULL;
+ up(&upperlayer_lock);
+}
+EXPORT_SYMBOL(tpm_fe_unregister_receiver);
+
+/*
+ * Call this function to send data to the upper layer's
+ * registered receiver function.
+ */
+static int tpm_fe_send_upperlayer(const u8 * buf, size_t count,
+ const void *ptr)
+{
+ int rc;
+
+ down(&upperlayer_lock);
+
+ if (upperlayer_tpmfe && upperlayer_tpmfe->receive) {
+ rc = upperlayer_tpmfe->receive(buf, count, ptr);
+ } else {
+ rc = 0;
+ }
+
+ up(&upperlayer_lock);
+ return rc;
+}
+
+/**************************************************************
+ XENBUS support code
+**************************************************************/
+
+static void watch_for_status(struct xenbus_watch *watch, const char *node)
+{
+ struct tpmfront_info *info;
+ int err;
+ unsigned long ready;
+ struct tpm_private *tp = &my_private;
+
+ info = container_of(watch, struct tpmfront_info, watch);
+ node += strlen(watch->node);
+
+ if (tp->connected)
+ return;
+
+ err = xenbus_gather(watch->node,
+ "ready", "%lu", &ready,
+ NULL);
+ if (err) {
+ xenbus_dev_error(info->dev, err, "reading 'ready' field");
+ return;
+ }
+
+ tpmif_set_connected_state(tp, 1);
+
+ xenbus_dev_ok(info->dev);
+}
+
+
+static int setup_tpmring(struct xenbus_device *dev,
+ struct tpmfront_info * info,
+ domid_t backend_id)
+{
+ tpmif_tx_interface_t *sring;
+ struct tpm_private *tp = &my_private;
+
+ evtchn_op_t op = { .cmd = EVTCHNOP_alloc_unbound };
+ int err;
+
+ sring = (void *)__get_free_page(GFP_KERNEL);
+ if (!sring) {
+ xenbus_dev_error(dev, -ENOMEM, "allocating shared ring");
+ return -ENOMEM;
+ }
+ tp->tx = sring;
+
+ tpm_allocate_buffers(tp);
+
+ info->ring_ref = gnttab_claim_grant_reference(&gref_head);
+ ASSERT(info->ring_ref != -ENOSPC);
+ gnttab_grant_foreign_access_ref(info->ring_ref,
+ backend_id,
+ (virt_to_machine(tp->tx) >> PAGE_SHIFT),
+ 0);
+
+ op.u.alloc_unbound.dom = backend_id;
+ err = HYPERVISOR_event_channel_op(&op);
+ if (err) {
+ free_page((unsigned long)sring);
+ tp->tx = 0;
+ xenbus_dev_error(dev, err, "allocating event channel");
+ return err;
+ }
+ tpmif_connect(op.u.alloc_unbound.port, backend_id);
+ return 0;
+}
+
+
+static void destroy_tpmring(struct tpmfront_info *info, struct tpm_private *tp)
+{
+ tpmif_set_connected_state(tp,0);
+
+ if ( tp->tx != NULL ) {
+ free_page((unsigned long)tp->tx);
+ tp->tx = NULL;
+ }
+ unbind_evtchn_from_irqhandler(tp->evtchn, NULL);
+ tp->evtchn = 0;
+}
+
+
+static int talk_to_backend(struct xenbus_device *dev,
+ struct tpmfront_info *info)
+{
+ char *backend;
+ const char *message;
+ int err;
+ int backend_id;
+
+ backend = NULL;
+ err = xenbus_gather(dev->nodename,
+ "backend-id", "%i", &backend_id,
+ "backend", NULL, &backend,
+ NULL);
+ if (XENBUS_EXIST_ERR(err))
+ goto out;
+ if (backend && strlen(backend) == 0) {
+ err = -ENOENT;
+ goto out;
+ }
+ if (err < 0) {
+ xenbus_dev_error(dev, err, "reading %s/backend or backend-id",
+ dev->nodename);
+ goto out;
+ }
+
+ info->backend_id = backend_id;
+ my_private.backend_id = backend_id;
+
+ err = setup_tpmring(dev, info, backend_id);
+ if (err) {
+ xenbus_dev_error(dev, err, "setting up ring");
+ goto out;
+ }
+
+ err = xenbus_transaction_start(dev->nodename);
+ if (err) {
+ xenbus_dev_error(dev, err, "starting transaction");
+ goto destroy_tpmring;
+ }
+
+ err = xenbus_printf(dev->nodename,
+ "ring-ref","%u", info->ring_ref);
+ if (err) {
+ message = "writing ring-ref";
+ goto abort_transaction;
+ }
+
+ err = xenbus_printf(dev->nodename,
+ "event-channel", "%u", my_private.evtchn);
+ if (err) {
+ message = "writing event-channel";
+ goto abort_transaction;
+ }
+
+ info->backend = backend;
+ backend = NULL;
+
+ info->watch.node = info->backend;
+ info->watch.callback = watch_for_status;
+ err = register_xenbus_watch(&info->watch);
+ if (err) {
+ message = "registering watch on backend";
+ goto abort_transaction;
+ }
+
+ err = xenbus_transaction_end(0);
+ if (err) {
+ xenbus_dev_error(dev, err, "completing transaction");
+ goto destroy_tpmring;
+ }
+
+out:
+ if (backend)
+ kfree(backend);
+ return err;
+
+abort_transaction:
+ xenbus_transaction_end(1);
+ /* Have to do this *outside* transaction. */
+ xenbus_dev_error(dev, err, "%s", message);
+destroy_tpmring:
+ destroy_tpmring(info, &my_private);
+ goto out;
+}
+
+
+static int tpmfront_probe(struct xenbus_device *dev,
+ const struct xenbus_device_id *id)
+{
+ int err;
+ struct tpmfront_info *info;
+ int handle;
+
+ err = xenbus_scanf(dev->nodename,
+ "handle", "%i", &handle);
+ if (XENBUS_EXIST_ERR(err))
+ return err;
+
+ if (err < 0) {
+ xenbus_dev_error(dev,err,"reading virtual-device");
+ return err;
+ }
+
+ info = kmalloc(sizeof(*info), GFP_KERNEL);
+ if (!info) {
+ xenbus_dev_error(dev,err,"allocating info structure");
+ return err;
+ }
+ memset(info, 0x0, sizeof(*info));
+
+ info->dev = dev;
+ info->handle = handle;
+ dev->data = info;
+
+ err = talk_to_backend(dev, info);
+ if (err) {
+ kfree(info);
+ dev->data = NULL;
+ return err;
+ }
+
+ watch_for_status(&info->watch, info->watch.node);
+ return 0;
+}
+
+static int tpmfront_remove(struct xenbus_device *dev)
+{
+ struct tpmfront_info *info = dev->data;
+ if (info->backend)
+ unregister_xenbus_watch(&info->watch);
+
+ destroy_tpmring(info, &my_private);
+
+ kfree(info->backend);
+ kfree(info);
+
+ return 0;
+}
+
+static int tpmfront_suspend(struct xenbus_device *dev)
+{
+ struct tpmfront_info *info = dev->data;
+ struct tpm_private *tp = &my_private;
+
+ /* lock so no app can send */
+ down(&suspend_lock);
+
+ while (atomic_read(&tp->tx_busy)) {
+ printk("---- TPMIF: Outstanding request.\n");
+#if 0
+ /*
+ * Would like to wait until the outstanding request
+ * has come back, but this does not work properly, yet.
+ */
+ interruptible_sleep_on_timeout(&tp->wait_q,
+ 100);
+#else
+ break;
+#endif
+ }
+
+ unregister_xenbus_watch(&info->watch);
+
+ kfree(info->backend);
+ info->backend = NULL;
+
+ destroy_tpmring(info, tp);
+
+ return 0;
+}
+
+static int tpmif_recover(void)
+{
+ return 0;
+}
+
+static int tpmfront_resume(struct xenbus_device *dev)
+{
+ struct tpmfront_info *info = dev->data;
+ int err;
+
+ err = talk_to_backend(dev, info);
+ if (!err) {
+ tpmif_recover();
+ }
+
+ /* unlock so apps can resume */
+ up(&suspend_lock);
+
+ return err;
+}
+
+static void tpmif_connect(u16 evtchn, domid_t domid)
+{
+ int err = 0;
+ struct tpm_private *tp = &my_private;
+
+ tp->evtchn = evtchn;
+ tp->backend_id = domid;
+
+ err = bind_evtchn_to_irqhandler(
+ tp->evtchn,
+ tpmif_int, SA_SAMPLE_RANDOM, "tpmif", tp);
+ if ( err != 0 ) {
+ WPRINTK("bind_evtchn_to_irqhandler failed (err=%d)\n", err);
+ return;
+ }
+}
+
+static struct xenbus_device_id tpmfront_ids[] = {
+ { "vtpm" },
+ { "" }
+};
+
+static struct xenbus_driver tpmfront = {
+ .name = "vtpm",
+ .owner = THIS_MODULE,
+ .ids = tpmfront_ids,
+ .probe = tpmfront_probe,
+ .remove = tpmfront_remove,
+ .resume = tpmfront_resume,
+ .suspend = tpmfront_suspend,
+};
+
+static void __init init_tpm_xenbus(void)
+{
+ xenbus_register_device(&tpmfront);
+}
+
+
+static int
+tpm_allocate_buffers(struct tpm_private *tp)
+{
+ unsigned int i;
+
+ i = 0;
+ while (i < TPMIF_TX_RING_SIZE) {
+ tp->tx_buffers[i] = tx_buffer_alloc();
+ i++;
+ }
+
+ return 1;
+}
+
+static void
+tpmif_rx_action(unsigned long unused)
+{
+ struct tpm_private *tp = &my_private;
+
+ int i = 0;
+ unsigned int received;
+ unsigned int offset = 0;
+ u8 *buffer;
+ tpmif_tx_request_t *tx;
+ tx = &tp->tx->ring[i].req;
+
+ received = tx->size;
+
+ buffer = kmalloc(received, GFP_KERNEL);
+ if (NULL == buffer) {
+ goto exit;
+ }
+
+ i = 0;
+ while (i < TPMIF_TX_RING_SIZE &&
+ offset < received) {
+ struct tx_buffer *txb = tp->tx_buffers[i];
+ tpmif_tx_request_t *tx;
+ unsigned int tocopy;
+
+ tx = &tp->tx->ring[i].req;
+ tocopy = tx->size;
+ if (tocopy > PAGE_SIZE) {
+ tocopy = PAGE_SIZE;
+ }
+
+ memcpy(&buffer[offset], txb->data, tocopy);
+
+ gnttab_release_grant_reference(&gref_head, tx->ref);
+
+ offset += tocopy;
+ i++;
+ }
+
+ tpm_fe_send_upperlayer(buffer, received, tp->tx_remember);
+ kfree(buffer);
+
+exit:
+ atomic_set(&tp->tx_busy, 0);
+ wake_up_interruptible(&tp->wait_q);
+}
+
+
+static irqreturn_t
+tpmif_int(int irq, void *tpm_priv, struct pt_regs *ptregs)
+{
+ struct tpm_private *tp = tpm_priv;
+ unsigned long flags;
+
+ spin_lock_irqsave(&tp->tx_lock, flags);
+ tasklet_schedule(&tpmif_rx_tasklet);
+ spin_unlock_irqrestore(&tp->tx_lock, flags);
+
+ return IRQ_HANDLED;
+}
+
+
+static int
+tpm_xmit(struct tpm_private *tp,
+ const u8 * buf, size_t count, int isuserbuffer,
+ void *remember)
+{
+ tpmif_tx_request_t *tx;
+ TPMIF_RING_IDX i;
+ unsigned int offset = 0;
+
+ spin_lock_irq(&tp->tx_lock);
+
+ if (unlikely(atomic_read(&tp->tx_busy))) {
+ printk("There's an outstanding request/response on the way!\n");
+ spin_unlock_irq(&tp->tx_lock);
+ return -EBUSY;
+ }
+
+ if (tp->connected != 1) {
+ spin_unlock_irq(&tp->tx_lock);
+ return -EIO;
+ }
+
+ i = 0;
+ while (count > 0 && i < TPMIF_TX_RING_SIZE) {
+ struct tx_buffer *txb = tp->tx_buffers[i];
+ int copied;
+
+ if (NULL == txb) {
+ DPRINTK("txb (i=%d) is NULL. buffers initilized?\n", i);
+ DPRINTK("Not transmittin anything!\n");
+ spin_unlock_irq(&tp->tx_lock);
+ return -EFAULT;
+ }
+ copied = tx_buffer_copy(txb, &buf[offset], count,
+ isuserbuffer);
+ if (copied < 0) {
+ /* An error occurred */
+ return copied;
+ }
+ count -= copied;
+ offset += copied;
+
+ tx = &tp->tx->ring[i].req;
+
+ tx->id = i;
+ tx->addr = virt_to_machine(txb->data);
+ tx->size = txb->len;
+
+ DPRINTK("First 4 characters sent by TPM-FE are 0x%02x 0x%02x
0x%02x 0x%02x\n",
+ txb->data[0],txb->data[1],txb->data[2],txb->data[3]);
+
+ /* get the granttable reference for this page */
+ tx->ref = gnttab_claim_grant_reference( &gref_head );
+
+ if(-ENOSPC == tx->ref ) {
+ DPRINTK(" Grant table claim reference failed in func:%s
line:%d file:%s\n", __FUNCTION__, __LINE__, __FILE__);
+ return -ENOSPC;
+ }
+ gnttab_grant_foreign_access_ref( tx->ref,
+ tp->backend_id,
+ (tx->addr >> PAGE_SHIFT),
+ 0 /*RW*/);
+ i++;
+ wmb();
+ }
+
+ atomic_set(&tp->tx_busy, 1);
+ tp->tx_remember = remember;
+ mb();
+
+ DPRINTK("Notifying backend via event channel %d\n",
+ tp->evtchn);
+
+ notify_via_evtchn(tp->evtchn);
+
+ spin_unlock_irq(&tp->tx_lock);
+ return offset;
+}
+
+
+static void tpmif_notify_upperlayer(struct tpm_private *tp)
+{
+ /*
+ * Notify upper layer about the state of the connection
+ * to the BE.
+ */
+ down(&upperlayer_lock);
+
+ if (upperlayer_tpmfe != NULL) {
+ switch (tp->connected) {
+ case 1:
+
upperlayer_tpmfe->status(TPMFE_STATUS_CONNECTED);
+ break;
+
+ default:
+ upperlayer_tpmfe->status(0);
+ break;
+ }
+ }
+ up(&upperlayer_lock);
+}
+
+
+static void tpmif_set_connected_state(struct tpm_private *tp, int newstate)
+{
+ if (newstate != tp->connected) {
+ tp->connected = newstate;
+ tpmif_notify_upperlayer(tp);
+ }
+}
+
+
+/* =================================================================
+ * Initialization function.
+ * =================================================================
+ */
+
+static int __init
+tpmif_init(void)
+{
+ IPRINTK("Initialising the vTPM driver.\n");
+ if ( gnttab_alloc_grant_references ( TPMIF_TX_RING_SIZE,
+ &gref_head ) < 0) {
+ return -EFAULT;
+ }
+ /*
+ * Only don't send the driver status when we are in the
+ * INIT domain.
+ */
+ spin_lock_init(&my_private.tx_lock);
+ init_waitqueue_head(&my_private.wait_q);
+
+ init_tpm_xenbus();
+
+ return 0;
+}
+
+__initcall(tpmif_init);
diff -r 84ab93e1ee05 -r dd668f7527cb
linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.h
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.h Thu Sep 1
10:16:14 2005
@@ -0,0 +1,38 @@
+#ifndef TPM_FRONT_H
+#define TPM_FRONT_H
+
+
+struct tpm_private {
+ tpmif_tx_interface_t *tx;
+ unsigned int evtchn;
+ int connected;
+
+ spinlock_t tx_lock;
+
+ struct tx_buffer *tx_buffers[TPMIF_TX_RING_SIZE];
+
+ atomic_t tx_busy;
+ void *tx_remember;
+ domid_t backend_id;
+ wait_queue_head_t wait_q;
+};
+
+
+struct tpmfront_info
+{
+ struct xenbus_watch watch;
+ int handle;
+ struct xenbus_device *dev;
+ char *backend;
+ int ring_ref;
+ domid_t backend_id;
+};
+
+
+struct tx_buffer {
+ unsigned int size; // available space in data
+ unsigned int len; // used space in data
+ unsigned char *data; // pointer to a page
+};
+
+#endif
diff -r 84ab93e1ee05 -r dd668f7527cb linux-2.6-xen-sparse/include/linux/tpmfe.h
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/linux-2.6-xen-sparse/include/linux/tpmfe.h Thu Sep 1 10:16:14 2005
@@ -0,0 +1,33 @@
+#ifndef TPM_FE_H
+#define TPM_FE_H
+
+struct tpmfe_device {
+ /*
+ * Let upper layer receive data from front-end
+ */
+ int (*receive)(const u8 *buffer, size_t count, const void *ptr);
+ /*
+ * Indicate the status of the front-end to the upper
+ * layer.
+ */
+ void (*status)(unsigned int flags);
+
+ /*
+ * This field indicates the maximum size the driver can
+ * transfer in one chunk. It is filled out by the front-end
+ * driver and should be propagated to the generic tpm driver
+ * for allocation of buffers.
+ */
+ unsigned int max_tx_size;
+};
+
+enum {
+ TPMFE_STATUS_DISCONNECTED = 0x0,
+ TPMFE_STATUS_CONNECTED = 0x1
+};
+
+int tpm_fe_send(const u8 * buf, size_t count, void *ptr);
+int tpm_fe_register_receiver(struct tpmfe_device *);
+void tpm_fe_unregister_receiver(void);
+
+#endif
diff -r 84ab93e1ee05 -r dd668f7527cb tools/python/xen/xend/server/tpmif.py
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/python/xen/xend/server/tpmif.py Thu Sep 1 10:16:14 2005
@@ -0,0 +1,52 @@
+# Copyright (C) 2005 IBM Corporation
+# Authort: Stefan Berger, stefanb@xxxxxxxxxx
+# Derived from netif.py:
+# Copyright (C) 2004 Mike Wray <mike.wray@xxxxxx>
+"""Support for virtual TPM interfaces.
+"""
+
+import random
+
+from xen.xend import sxp
+from xen.xend.XendError import XendError, VmError
+from xen.xend.XendLogging import log
+from xen.xend.XendRoot import get_component
+from xen.xend.xenstore import DBVar
+
+from xen.xend.server import channel
+from xen.xend.server.controller import CtrlMsgRcvr, Dev, DevController
+from xen.xend.server.messages import *
+
+class TPMifController(DevController):
+ """TPM interface controller. Handles all TPM devices for a domain.
+ """
+
+ def __init__(self, vm, recreate=False):
+ DevController.__init__(self, vm, recreate=recreate)
+ self.rcvr = None
+ self.channel = None
+
+ def initController(self, recreate=False, reboot=False):
+ self.destroyed = False
+ self.channel = self.getChannel()
+
+ def destroyController(self, reboot=False):
+ """Destroy the controller and all devices.
+ """
+ self.destroyed = True
+ self.destroyDevices(reboot=reboot)
+ if self.rcvr:
+ self.rcvr.deregisterChannel()
+
+ def sxpr(self):
+ val = ['tpmif', ['dom', self.getDomain()]]
+ return val
+
+ def newDevice(self, id, config, recreate=False):
+ """Create a TPM device.
+
+ @param id: interface id
+ @param config: device configuration
+ @param recreate: recreate flag (true after xend restart)
+ """
+ return None
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm/Makefile
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm/Makefile Thu Sep 1 10:16:14 2005
@@ -0,0 +1,63 @@
+XEN_ROOT = ../..
+
+# Base definitions and rules
+include $(XEN_ROOT)/tools/vtpm/Rules.mk
+
+# Dir name for emulator (as dom0 tpm driver)
+TPM_EMULATOR_DIR = tpm_emulator-0.2
+# Dir name for vtpm instance
+VTPM_DIR = vtpm
+
+# Emulator tarball name
+TPM_EMULATOR_TARFILE = tpm_emulator-0.2b.tar.gz
+
+all: build
+
+build: $(TPM_EMULATOR_TARFILE) extract patch build_sub
+
+install: build
+ $(MAKE) -C $(TPM_EMULATOR_DIR) $@
+ $(MAKE) -C $(VTPM_DIR) $@
+
+clean:
+ if [ -d $(TPM_EMULATOR_DIR) ]; \
+ then $(MAKE) -C $(TPM_EMULATOR_DIR) clean; \
+ fi
+ if [ -d $(VTPM_DIR) ]; \
+ then $(MAKE) -C $(VTPM_DIR) clean; \
+ fi
+ rm -rf $(TPM_EMULATOR_DIR)
+ rm -rf $(VTPM_DIR)
+
+mrproper: clean
+ rm -f $(TPM_EMULATOR_TARFILE)
+
+# Download Swiss emulator
+$(TPM_EMULATOR_TARFILE):
+ wget http://download.berlios.de/tpm-emulator/$(TPM_EMULATOR_TARFILE)
+
+# Create vtpm and TPM emulator dirs
+extract: $(TPM_EMULATOR_DIR)/README $(VTPM_DIR)/README
+
+$(TPM_EMULATOR_DIR)/README:
+ -rm -rf $(TPM_EMULATOR_DIR)
+ tar -xzf $(TPM_EMULATOR_TARFILE)
+
+$(VTPM_DIR)/README:
+ -rm -rf $(VTPM_DIR)
+ cp -r --preserve $(TPM_EMULATOR_DIR) $(VTPM_DIR)
+
+# apply patches for 1) used as dom0 tpm driver 2) used as vtpm device instance
+patch: $(TPM_EMULATOR_DIR)/Makefile $(VTPM_DIR)/Makefile
+
+$(TPM_EMULATOR_DIR)/Makefile: tpm_emulator.patch
+ -cd $(TPM_EMULATOR_DIR); \
+ patch -p1 <../tpm_emulator.patch
+
+$(VTPM_DIR)/Makefile: vtpm.patch
+ -cd $(VTPM_DIR); \
+ patch -p1 <../vtpm.patch
+
+build_sub:
+ $(MAKE) -C $(TPM_EMULATOR_DIR)
+ $(MAKE) -C $(VTPM_DIR)
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm/README
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm/README Thu Sep 1 10:16:14 2005
@@ -0,0 +1,44 @@
+
+Directory Structure
+===================
+tools/vtpm/tpm_emulator-0.2b.tar.gz -> TPM Emulator downloaded at build
time that will
+ be patched and used for our vtpms
+tools/vtpm/vtpm.patch -> patch applied to tpm_emulator to
make vtpm
+tools/vtpm/vtpm/ -> (created on build) tpm_emulator
moved to ring 3,
+ listens on a pair of fifos for TPM
commands,
+ persistent state is sent via named
fifo to vtpm
+ manager, which encrypts it and
protects it.
+tools/vtpm/tpm_emulator.patch -> To allow for debugging and testing
on non-TPM
+ platforms, this patches the emulator
to allow
+ it to be inserted into the dom0
kernel
+tools/vtpm/tpm_emulator-0.2 -> (created on build) directory
containing patched emulator
+
+Compile Flags
+===================
+VTPM_MULTI_VM -> Defined (not finished): VTPMs run in their own
VMs
+ Not Defined (default): VTPMs are processes
+
+Requirements
+============
+- xen-unstable
+- IBM frontend/backend vtpm driver patch
+- vtpm_managerd
+
+vtpmd Flow (for vtpm_manager. vtpmd never run by default)
+============================
+- Launch the VTPM manager (vtpm_managerd) which which begins listening to the
BE with one thread
+ and listens to a named fifo that is shared by the vtpms to commuincate with
the manager.
+- VTPM Manager listens to TPM BE.
+- When xend launches a tpm frontend equipped VM it contacts the manager over
the vtpm backend.
+- When the manager receives the open message from the BE, it launches a vtpm
+- Xend allows the VM to continue booting.
+- When a TPM request is issued to the front end, the front end transmits the
TPM request to the backend.
+- The manager receives the TPM requests and uses a named fifo to forward the
request to the vtpm.
+- The fifo listener begins listening for the reply from vtpm for the request.
+- Vtpm processes request and replies to manager over shared named fifo.
+- If needed, the vtpm may send a request to the vtpm_manager at any time to
save it's secrets to disk.
+- Manager receives response from vtpm and passes it back to backend for
forwarding to guest.
+
+tpm_emulator flow
+==================
+Read documentation in tpm_emulator-0.2 directory
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm/Rules.mk
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm/Rules.mk Thu Sep 1 10:16:14 2005
@@ -0,0 +1,37 @@
+# Base definitions and rules (XEN_ROOT must be defined in including Makefile)
+include $(XEN_ROOT)/tools/Rules.mk
+
+#
+# Tool definitions
+#
+
+# Installation program and options
+INSTALL = install
+INSTALL_PROG = $(INSTALL) -m0755
+INSTALL_DIR = $(INSTALL) -d -m0755
+
+# Xen tools installation directory
+TOOLS_INSTALL_DIR = $(DESTDIR)/usr/bin
+
+# General compiler flags
+CFLAGS = -Wall -Werror -g3 -I.
+
+# For generating dependencies
+CFLAGS += -Wp,-MD,.$(@F).d
+
+DEP_FILES = .*.d
+
+# Generic project files
+HDRS = $(wildcard *.h)
+SRCS = $(wildcard *.c)
+OBJS = $(patsubst %.c,%.o,$(SRCS))
+
+# Generic (non-header) dependencies
+$(SRCS): Makefile $(XEN_ROOT)/tools/Rules.mk $(XEN_ROOT)/tools/vtpm/Rules.mk
+
+$(OBJS): $(SRCS)
+
+-include $(DEP_FILES)
+
+# Make sure these are just rules
+.PHONY : all build install clean
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm/tpm_emulator.patch
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm/tpm_emulator.patch Thu Sep 1 10:16:14 2005
@@ -0,0 +1,151 @@
+diff -uprN orig/tpm_emulator-0.2/AUTHORS tpm_emulator-0.2/AUTHORS
+--- orig/tpm_emulator-0.2/AUTHORS 2005-08-17 10:58:36.000000000 -0700
++++ tpm_emulator-0.2/AUTHORS 2005-08-17 10:55:52.000000000 -0700
+@@ -1 +1,2 @@
+ Mario Strasser <mast@xxxxxxx>
++INTEL Corp <>
+diff -uprN orig/tpm_emulator-0.2/ChangeLog tpm_emulator-0.2/ChangeLog
+--- orig/tpm_emulator-0.2/ChangeLog 2005-08-17 10:58:36.000000000 -0700
++++ tpm_emulator-0.2/ChangeLog 2005-08-17 10:55:52.000000000 -0700
+@@ -1,3 +1,7 @@
++2005-08-16: INTEL Corp
++ * Set default permissions to PCRs
++ * Changed device to /dev/tpm0
++
+ 2005-08-15 Mario Strasser <mast@xxxxxxx>
+ * all: some typos corrected
+ * tpm_integrity.c: bug in TPM_Extend fixed
+diff -uprN orig/tpm_emulator-0.2/Makefile tpm_emulator-0.2/Makefile
+--- orig/tpm_emulator-0.2/Makefile 2005-08-17 10:58:36.000000000 -0700
++++ tpm_emulator-0.2/Makefile 2005-08-17 10:55:52.000000000 -0700
+@@ -1,15 +1,19 @@
+ # Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ # Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>
++# Copyright (C) 2005 INTEL Corp.
+ #
+ # $Id: Makefile 10 2005-04-26 20:59:50Z mast $
+
++XEN_ROOT := ../../..
++EUID := $(shell id -u)
++
+ # kernel settings
+ KERNEL_RELEASE := $(shell uname -r)
+-KERNEL_BUILD := /lib/modules/$(KERNEL_RELEASE)/build
++KERNEL_BUILD := $(XEN_ROOT)/linux-2.6.12-xen0
+ MOD_SUBDIR := misc
+
+ # module settings
+-MODULE_NAME := tpm_emulator
++BIN := tpm_emulator
+ VERSION_MAJOR := 0
+ VERSION_MINOR := 2
+ VERSION_BUILD := $(shell date +"%s")
+@@ -27,11 +30,9 @@ DIRS := . crypto tpm
+ SRCS := $(foreach dir, $(DIRS), $(wildcard $(src)/$(dir)/*.c))
+ OBJS := $(patsubst %.c, %.o, $(SRCS))
+ SRCS += $(foreach dir, $(DIRS), $(wildcard $(src)/$(dir)/*.h))
+-DISTSRC := ./README ./AUTHORS ./ChangeLog ./Makefile $(SRCS)
+-DISTDIR := tpm_emulator-$(VERSION_MAJOR).$(VERSION_MINOR)
+
+-obj-m := $(MODULE_NAME).o
+-$(MODULE_NAME)-objs := $(patsubst $(src)/%.o, %.o, $(OBJS)) crypto/libgmp.a
++obj-m := $(BIN).o
++$(BIN)-objs := $(patsubst $(src)/%.o, %.o, $(OBJS)) crypto/libgmp.a
+
+ EXTRA_CFLAGS += -I$(src) -I$(src)/crypto -I$(src)/tpm
+
+@@ -42,23 +43,17 @@ all: $(src)/crypto/gmp.h $(src)/crypto/l
+ @$(MAKE) -C $(KERNEL_BUILD) M=$(CURDIR) modules
+
+ install:
+- @$(MAKE) -C $(KERNEL_BUILD) M=$(CURDIR) modules_install
+- test -d /var/tpm || mkdir /var/tpm
+- test -c /dev/tpm || mknod /dev/tpm c 10 224
+- chmod 666 /dev/tpm
+- depmod -a
++ @$(MAKE) -C $(KERNEL_BUILD) M=$(CURDIR) INSTALL_MOD_PATH=$(DESTDIR)
modules_install
++ test -d $(DESTDIR)/var/tpm || mkdir $(DESTDIR)/var/tpm
++ test -d $(DESTDIR)/dev || mkdir $(DESTDIR)/dev
++ test -c $(DESTDIR)/dev/tpm0 || [ $(EUID) -ne 0 ] || mknod
$(DESTDIR)/dev/tpm0 c 10 224
++ [ $(EUID) -ne 0 ] || chmod 666 $(DESTDIR)/dev/tpm0
+
+ clean:
+ @$(MAKE) -C $(KERNEL_BUILD) M=$(CURDIR) clean
+ rm -f $(src)/crypto/gmp.h $(src)/crypto/libgmp.a
+
+-dist: $(DISTSRC)
+- rm -rf $(DISTDIR)
+- mkdir $(DISTDIR)
+- cp --parents $(DISTSRC) $(DISTDIR)/
+- rm -f $(DISTDIR)/crypto/gmp.h
+- tar -chzf $(DISTDIR).tar.gz $(DISTDIR)
+- rm -rf $(DISTDIR)
++mrproper: clean
+
+ $(src)/crypto/libgmp.a:
+ test -f $(src)/crypto/libgmp.a || ln -s $(GMP_LIB)
$(src)/crypto/libgmp.a
+diff -uprN orig/tpm_emulator-0.2/README tpm_emulator-0.2/README
+--- orig/tpm_emulator-0.2/README 2005-08-17 10:58:36.000000000 -0700
++++ tpm_emulator-0.2/README 2005-08-17 10:55:52.000000000 -0700
+@@ -13,7 +13,8 @@ $Id: README 8 2005-01-25 21:11:45Z jmoli
+ Copyright
+ --------------------------------------------------------------------------
+ Copyright (C) 2004 Mario Strasser <mast@xxxxxxx> and Swiss Federal
+-Institute of Technology (ETH) Zurich.
++ Institute of Technology (ETH) Zurich.
++Copyright (C) 2005
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+diff -uprN orig/tpm_emulator-0.2/linux_module.h tpm_emulator-0.2/linux_module.h
+--- orig/tpm_emulator-0.2/linux_module.h 2005-08-17 10:58:36.000000000
-0700
++++ tpm_emulator-0.2/linux_module.h 2005-08-17 10:55:52.000000000 -0700
+@@ -1,5 +1,6 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
++ * Copyright (C) 2005 INTEL Corp.
+ *
+ * This module is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+@@ -33,7 +34,7 @@
+ #include "tpm_version.h"
+
+ #define TPM_DEVICE_MINOR 224
+-#define TPM_DEVICE_NAME "tpm"
++#define TPM_DEVICE_NAME "tpm0"
+ #define TPM_MODULE_NAME "tpm_emulator"
+
+ /* debug and log output functions */
+diff -uprN orig/tpm_emulator-0.2/tpm/tpm_data.c tpm_emulator-0.2/tpm/tpm_data.c
+--- orig/tpm_emulator-0.2/tpm/tpm_data.c 2005-08-17 10:58:36.000000000
-0700
++++ tpm_emulator-0.2/tpm/tpm_data.c 2005-08-17 10:55:52.000000000 -0700
+@@ -1,6 +1,7 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
+ * Swiss Federal Institute of Technology (ETH) Zurich
++ * Copyright (C) 2005 INTEL Corp
+ *
+ * This module is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+@@ -85,6 +86,11 @@ void tpm_init_data(void)
+ tpmData.permanent.data.version.revMinor = VERSION_MINOR;
+ /* setup PCR attributes */
+ for (i = 0; i < TPM_NUM_PCR; i++) {
++ int j;
++ for (j=0; j < TPM_NUM_LOCALITY; j++) {
++ tpmData.permanent.data.pcrAttrib[i].pcrExtendLocal[j] = TRUE;
++ }
++
+ tpmData.permanent.data.pcrAttrib[i].pcrReset = TRUE;
+ }
+ /* set tick type */
+diff -uprN orig/tpm_emulator-0.2/tpm_version.h tpm_emulator-0.2/tpm_version.h
+--- orig/tpm_emulator-0.2/tpm_version.h 2005-08-17 10:58:36.000000000
-0700
++++ tpm_emulator-0.2/tpm_version.h 2005-08-17 10:55:53.000000000 -0700
+@@ -2,5 +2,5 @@
+ #define _TPM_VERSION_H_
+ #define VERSION_MAJOR 0
+ #define VERSION_MINOR 2
+-#define VERSION_BUILD 1123950310
++#define VERSION_BUILD 1124301353
+ #endif /* _TPM_VERSION_H_ */
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm/vtpm.patch
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm/vtpm.patch Thu Sep 1 10:16:14 2005
@@ -0,0 +1,1645 @@
+diff -uprN orig/tpm_emulator-0.2/AUTHORS vtpm/AUTHORS
+--- orig/tpm_emulator-0.2/AUTHORS 2005-08-17 10:58:36.000000000 -0700
++++ vtpm/AUTHORS 2005-08-17 10:55:52.000000000 -0700
+@@ -1 +1,2 @@
+ Mario Strasser <mast@xxxxxxx>
++INTEL Corp <>
+diff -uprN orig/tpm_emulator-0.2/ChangeLog vtpm/ChangeLog
+--- orig/tpm_emulator-0.2/ChangeLog 2005-08-17 10:58:36.000000000 -0700
++++ vtpm/ChangeLog 2005-08-17 10:55:52.000000000 -0700
+@@ -1,3 +1,7 @@
++2005-08-16 Intel Corp
++ Moved module out of kernel to run as a ring 3 app
++ Modified save_to_file and load_from_file to call a xen backend driver
to call a VTPM manager
++
+ 2005-08-15 Mario Strasser <mast@xxxxxxx>
+ * all: some typos corrected
+ * tpm_integrity.c: bug in TPM_Extend fixed
+diff -uprN orig/tpm_emulator-0.2/Makefile vtpm/Makefile
+--- orig/tpm_emulator-0.2/Makefile 2005-08-17 10:58:36.000000000 -0700
++++ vtpm/Makefile 2005-08-17 10:55:52.000000000 -0700
+@@ -1,21 +1,29 @@
+ # Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ # Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>
++# Copyright (C) 2005 INTEL Corp.
+ #
+ # $Id: Makefile 10 2005-04-26 20:59:50Z mast $
+
+-# kernel settings
+-KERNEL_RELEASE := $(shell uname -r)
+-KERNEL_BUILD := /lib/modules/$(KERNEL_RELEASE)/build
+-MOD_SUBDIR := misc
+-
+ # module settings
+-MODULE_NAME := tpm_emulator
++BIN := vtpmd
+ VERSION_MAJOR := 0
+ VERSION_MINOR := 2
+ VERSION_BUILD := $(shell date +"%s")
+
+-# enable/disable DEBUG messages
+-EXTRA_CFLAGS += -DDEBUG -g
++# Installation program and options
++INSTALL = install
++INSTALL_PROG = $(INSTALL) -m0755
++INSTALL_DIR = $(INSTALL) -d -m0755
++
++# Xen tools installation directory
++TOOLS_INSTALL_DIR = $(DESTDIR)/usr/bin
++
++CC := gcc
++CFLAGS += -g -Wall $(INCLUDE) -DDEBUG
++CFLAGS += -I. -Itpm
++
++# Is the simulator running in it's own vm?
++#CFLAGS += -DVTPM_MULTI_VM
+
+ # GNU MP configuration
+ GMP_LIB := /usr/lib/libgmp.a
+@@ -27,38 +35,31 @@ DIRS := . crypto tpm
+ SRCS := $(foreach dir, $(DIRS), $(wildcard $(src)/$(dir)/*.c))
+ OBJS := $(patsubst %.c, %.o, $(SRCS))
+ SRCS += $(foreach dir, $(DIRS), $(wildcard $(src)/$(dir)/*.h))
+-DISTSRC := ./README ./AUTHORS ./ChangeLog ./Makefile $(SRCS)
+-DISTDIR := tpm_emulator-$(VERSION_MAJOR).$(VERSION_MINOR)
+
+-obj-m := $(MODULE_NAME).o
+-$(MODULE_NAME)-objs := $(patsubst $(src)/%.o, %.o, $(OBJS)) crypto/libgmp.a
++obj-m := $(BIN)
++$(BIN)-objs := $(patsubst $(src)/%.o, %.o, $(OBJS)) crypto/libgmp.a
+
+ EXTRA_CFLAGS += -I$(src) -I$(src)/crypto -I$(src)/tpm
+
+ # do not print "Entering directory ..."
+ MAKEFLAGS += --no-print-directory
+
+-all: $(src)/crypto/gmp.h $(src)/crypto/libgmp.a version
+- @$(MAKE) -C $(KERNEL_BUILD) M=$(CURDIR) modules
++all: $(BIN)
++
++$(BIN): $(src)/crypto/gmp.h $(src)/crypto/libgmp.a version $(SRCS)
$(OBJS)
++ $(CC) $(CFLAGS) $(OBJS) $(src)/crypto/libgmp.a -o $(BIN)
++
++%.o: %.c
++ $(CC) $(CFLAGS) -c $< -o $@
+
+ install:
+- @$(MAKE) -C $(KERNEL_BUILD) M=$(CURDIR) modules_install
+- test -d /var/tpm || mkdir /var/tpm
+- test -c /dev/tpm || mknod /dev/tpm c 10 224
+- chmod 666 /dev/tpm
+- depmod -a
++ $(INSTALL_PROG) $(BIN) $(TOOLS_INSTALL_DIR)
+
+ clean:
+- @$(MAKE) -C $(KERNEL_BUILD) M=$(CURDIR) clean
+- rm -f $(src)/crypto/gmp.h $(src)/crypto/libgmp.a
++ rm -f $(src)/crypto/gmp.h $(src)/crypto/libgmp.a $(OBJS)
+
+-dist: $(DISTSRC)
+- rm -rf $(DISTDIR)
+- mkdir $(DISTDIR)
+- cp --parents $(DISTSRC) $(DISTDIR)/
+- rm -f $(DISTDIR)/crypto/gmp.h
+- tar -chzf $(DISTDIR).tar.gz $(DISTDIR)
+- rm -rf $(DISTDIR)
++mrproper: clean
++ rm -f $(BIN)
+
+ $(src)/crypto/libgmp.a:
+ test -f $(src)/crypto/libgmp.a || ln -s $(GMP_LIB)
$(src)/crypto/libgmp.a
+diff -uprN orig/tpm_emulator-0.2/README vtpm/README
+--- orig/tpm_emulator-0.2/README 2005-08-17 10:58:36.000000000 -0700
++++ vtpm/README 2005-08-17 10:55:52.000000000 -0700
+@@ -13,7 +13,8 @@ $Id: README 8 2005-01-25 21:11:45Z jmoli
+ Copyright
+ --------------------------------------------------------------------------
+ Copyright (C) 2004 Mario Strasser <mast@xxxxxxx> and Swiss Federal
+-Institute of Technology (ETH) Zurich.
++ Institute of Technology (ETH) Zurich.
++Copyright (C) 2005 INTEL Corp
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+diff -uprN orig/tpm_emulator-0.2/crypto/gmp_kernel_wrapper.c
vtpm/crypto/gmp_kernel_wrapper.c
+--- orig/tpm_emulator-0.2/crypto/gmp_kernel_wrapper.c 2005-08-17
10:58:36.000000000 -0700
++++ vtpm/crypto/gmp_kernel_wrapper.c 2005-08-17 10:55:52.000000000 -0700
+@@ -1,5 +1,6 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
++ * Copyright (C) 2005 INTEL Corp
+ *
+ * This module is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+@@ -24,15 +25,10 @@ int __gmp_junk;
+ void __attribute__ ((regparm(0))) __gmp_assert_fail(const char *filename,
+ int linenum, const char *expr)
+ {
+- panic(KERN_CRIT TPM_MODULE_NAME "%s:%d: GNU MP assertion failed: %s\n",
++ error("%s:%d: GNU MP assertion failed: %s\n",
+ filename, linenum, expr);
+ }
+
+-void __attribute__ ((regparm(0))) abort(void)
+-{
+- panic(KERN_CRIT TPM_MODULE_NAME "GNU MP abort() was called\n");
+-}
+-
+ /* overwrite GNU MP random functions (used by mpz/millerrabin.c) */
+
+ void __attribute__ ((regparm(0))) gmp_randinit(gmp_randstate_t rstate,
+@@ -77,20 +73,19 @@ void __attribute__ ((regparm(0))) mpz_ur
+
+ void __attribute__ ((regparm(0))) *kernel_allocate(size_t size)
+ {
+- void *ret = (void*)kmalloc(size, GFP_KERNEL);
+- if (!ret) panic(KERN_CRIT TPM_MODULE_NAME
+- "GMP: cannot allocate memory (size=%u)\n", size);
++ void *ret = (void*)malloc(size);
++ if (!ret) error("GMP: cannot allocate memory (size=%u)\n", size);
+ return ret;
+ }
+
+ void __attribute__ ((regparm(0))) *kernel_reallocate(void *oldptr,
+ size_t old_size, size_t new_size)
+ {
+- void *ret = (void*)kmalloc(new_size, GFP_KERNEL);
+- if (!ret) panic(KERN_CRIT TPM_MODULE_NAME "GMP: Cannot reallocate memory "
++ void *ret = (void*)malloc(new_size);
++ if (!ret) error("GMP: Cannot reallocate memory "
+ "(old_size=%u new_size=%u)\n", old_size, new_size);
+ memcpy(ret, oldptr, old_size);
+- kfree(oldptr);
++ free(oldptr);
+ return ret;
+ }
+
+@@ -99,7 +94,7 @@ void __attribute__ ((regparm(0))) kernel
+ /* overwrite used memory */
+ if (blk_ptr != NULL) {
+ memset(blk_ptr, 0, blk_size);
+- kfree(blk_ptr);
++ free(blk_ptr);
+ }
+ }
+
+diff -uprN orig/tpm_emulator-0.2/crypto/rsa.c vtpm/crypto/rsa.c
+--- orig/tpm_emulator-0.2/crypto/rsa.c 2005-08-17 10:58:36.000000000 -0700
++++ vtpm/crypto/rsa.c 2005-08-17 10:55:52.000000000 -0700
+@@ -1,5 +1,6 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
++ * Copyright (C) 2005 INTEL Corp
+ *
+ * This module is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+@@ -363,7 +364,7 @@ static int encode_message(int type, uint
+ msg[0] = 0x00;
+ get_random_bytes(&msg[1], SHA1_DIGEST_LENGTH);
+ sha1_init(&ctx);
+- sha1_update(&ctx, "TCPA", 4);
++ sha1_update(&ctx, (uint8_t *) "TCPA", 4);
+ sha1_final(&ctx, &msg[1 + SHA1_DIGEST_LENGTH]);
+ memset(&msg[1 + 2 * SHA1_DIGEST_LENGTH], 0x00,
+ msg_len - data_len - 2 * SHA1_DIGEST_LENGTH - 2);
+@@ -411,7 +412,7 @@ static int decode_message(int type, uint
+ mask_generation(&msg[1], SHA1_DIGEST_LENGTH,
+ &msg[1 + SHA1_DIGEST_LENGTH], msg_len - SHA1_DIGEST_LENGTH - 1);
+ sha1_init(&ctx);
+- sha1_update(&ctx, "TCPA", 4);
++ sha1_update(&ctx, (uint8_t *) "TCPA", 4);
+ sha1_final(&ctx, &msg[1]);
+ if (memcmp(&msg[1], &msg[1 + SHA1_DIGEST_LENGTH],
+ SHA1_DIGEST_LENGTH) != 0) return -1;
+diff -uprN orig/tpm_emulator-0.2/linux_module.c vtpm/linux_module.c
+--- orig/tpm_emulator-0.2/linux_module.c 2005-08-17 10:58:36.000000000
-0700
++++ vtpm/linux_module.c 1969-12-31 16:00:00.000000000 -0800
+@@ -1,163 +0,0 @@
+-/* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+- * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
+- *
+- * This module is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published
+- * by the Free Software Foundation; either version 2 of the License,
+- * or (at your option) any later version.
+- *
+- * This module is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * $Id: linux_module.c 19 2005-05-18 08:29:37Z mast $
+- */
+-
+-#include <linux/module.h>
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/miscdevice.h>
+-#include <linux/poll.h>
+-#include "linux_module.h"
+-#include "tpm/tpm_emulator.h"
+-
+-MODULE_LICENSE("GPL");
+-MODULE_AUTHOR("Mario Strasser <mast@xxxxxxx>");
+-MODULE_DESCRIPTION("Trusted Platform Module (TPM) Emulator");
+-MODULE_SUPPORTED_DEVICE(TPM_DEVICE_NAME);
+-
+-/* module startup parameters */
+-char *startup = "save";
+-MODULE_PARM(startup, "s");
+-MODULE_PARM_DESC(startup, " Sets the startup mode of the TPM. "
+- "Possible values are 'clear', 'save' (default) and 'deactivated.");
+-char *storage_file = "/var/tpm/tpm_emulator-1.2.0.1";
+-MODULE_PARM(storage_file, "s");
+-MODULE_PARM_DESC(storage_file, " Sets the persistent-data storage "
+- "file of the TPM.");
+-
+-/* TPM lock */
+-static struct semaphore tpm_mutex;
+-
+-/* TPM command response */
+-static struct {
+- uint8_t *data;
+- uint32_t size;
+-} tpm_response;
+-
+-/* module state */
+-#define STATE_IS_OPEN 0
+-static uint32_t module_state;
+-
+-static int tpm_open(struct inode *inode, struct file *file)
+-{
+- debug("%s()", __FUNCTION__);
+- if (test_and_set_bit(STATE_IS_OPEN, (void*)&module_state)) return -EBUSY;
+- return 0;
+-}
+-
+-static int tpm_release(struct inode *inode, struct file *file)
+-{
+- debug("%s()", __FUNCTION__);
+- clear_bit(STATE_IS_OPEN, (void*)&module_state);
+- return 0;
+-}
+-
+-static ssize_t tpm_read(struct file *file, char *buf, size_t count, loff_t
*ppos)
+-{
+- debug("%s(%d)", __FUNCTION__, count);
+- down(&tpm_mutex);
+- if (tpm_response.data != NULL) {
+- count = min(count, (size_t)tpm_response.size - (size_t)*ppos);
+- count -= copy_to_user(buf, &tpm_response.data[*ppos], count);
+- *ppos += count;
+- } else {
+- count = 0;
+- }
+- up(&tpm_mutex);
+- return count;
+-}
+-
+-static ssize_t tpm_write(struct file *file, const char *buf, size_t count,
loff_t *ppos)
+-{
+- debug("%s(%d)", __FUNCTION__, count);
+- down(&tpm_mutex);
+- *ppos = 0;
+- if (tpm_response.data != NULL) kfree(tpm_response.data);
+- if (tpm_handle_command(buf, count, &tpm_response.data,
+- &tpm_response.size) != 0) {
+- count = -EILSEQ;
+- tpm_response.data = NULL;
+- }
+- up(&tpm_mutex);
+- return count;
+-}
+-
+-static int tpm_ioctl(struct inode *inode, struct file *file, unsigned int
cmd, unsigned long arg)
+-{
+- debug("%s(%d, %ld)", __FUNCTION__, cmd, arg);
+- return -1;
+-}
+-
+-struct file_operations fops = {
+- .owner = THIS_MODULE,
+- .open = tpm_open,
+- .release = tpm_release,
+- .read = tpm_read,
+- .write = tpm_write,
+- .ioctl = tpm_ioctl,
+-};
+-
+-static struct miscdevice tpm_dev = {
+- .minor = TPM_DEVICE_MINOR,
+- .name = TPM_DEVICE_NAME,
+- .fops = &fops,
+-};
+-
+-int __init init_tpm_module(void)
+-{
+- int res = misc_register(&tpm_dev);
+- if (res != 0) {
+- error("misc_register() failed for minor %d\n", TPM_DEVICE_MINOR);
+- return res;
+- }
+- /* initialize variables */
+- sema_init(&tpm_mutex, 1);
+- module_state = 0;
+- tpm_response.data = NULL;
+- /* initialize TPM emulator */
+- if (!strcmp(startup, "clear")) {
+- tpm_emulator_init(1);
+- } else if (!strcmp(startup, "save")) {
+- tpm_emulator_init(2);
+- } else if (!strcmp(startup, "deactivated")) {
+- tpm_emulator_init(3);
+- } else {
+- error("invalid startup mode '%s'; must be 'clear', "
+- "'save' (default) or 'deactivated", startup);
+- misc_deregister(&tpm_dev);
+- return -EINVAL;
+- }
+- return 0;
+-}
+-
+-void __exit cleanup_tpm_module(void)
+-{
+- tpm_emulator_shutdown();
+- misc_deregister(&tpm_dev);
+-}
+-
+-module_init(init_tpm_module);
+-module_exit(cleanup_tpm_module);
+-
+-uint64_t tpm_get_ticks(void)
+-{
+- static struct timespec old_time = {0, 0};
+- struct timespec new_time = current_kernel_time();
+- uint64_t ticks = (uint64_t)(old_time.tv_sec - new_time.tv_sec) * 1000000
+- + (old_time.tv_nsec - new_time.tv_nsec) / 1000;
+- old_time = new_time;
+- return (ticks > 0) ? ticks : 1;
+-}
+-
+diff -uprN orig/tpm_emulator-0.2/linux_module.h vtpm/linux_module.h
+--- orig/tpm_emulator-0.2/linux_module.h 2005-08-17 10:58:36.000000000
-0700
++++ vtpm/linux_module.h 2005-08-17 10:55:52.000000000 -0700
+@@ -1,5 +1,6 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
++ * Copyright (C) 2005 INTEL Corp
+ *
+ * This module is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+@@ -17,17 +18,22 @@
+ #ifndef _LINUX_MODULE_H_
+ #define _LINUX_MODULE_H_
+
+-#include <linux/version.h>
+-#include <linux/kernel.h>
+-#include <linux/slab.h>
++#include <malloc.h>
++#include <stdint.h>
++#include <stdio.h>
++#include <string.h>
+ #include <linux/types.h>
+-#include <linux/string.h>
+-#include <linux/random.h>
+-#include <linux/time.h>
+-#include <asm/byteorder.h>
+
+-/* module settings */
++#include <endian.h>
++#define __BYTEORDER_HAS_U64__
++#ifdef LITTLE_ENDIAN
++ #include <linux/byteorder/little_endian.h>
++#else
++ #include <linux/byteorder/big_endian.h>
++#endif
+
++/* module settings */
++#define min(A,B) ((A)<(B)?(A):(B))
+ #define STR(s) __STR__(s)
+ #define __STR__(s) #s
+ #include "tpm_version.h"
+@@ -39,32 +45,35 @@
+ /* debug and log output functions */
+
+ #ifdef DEBUG
+-#define debug(fmt, ...) printk(KERN_DEBUG "%s %s:%d: Debug: " fmt "\n", \
+- TPM_MODULE_NAME, __FILE__, __LINE__, ## __VA_ARGS__)
++#define debug(fmt, ...) printf("%s:%d: Debug: " fmt "\n", \
++ __FILE__, __LINE__, ## __VA_ARGS__)
+ #else
+ #define debug(fmt, ...)
+ #endif
+-#define info(fmt, ...) printk(KERN_INFO "%s %s:%d: Info: " fmt "\n", \
+- TPM_MODULE_NAME, __FILE__, __LINE__, ## __VA_ARGS__)
+-#define error(fmt, ...) printk(KERN_ERR "%s %s:%d: Error: " fmt "\n", \
+- TPM_MODULE_NAME, __FILE__, __LINE__, ## __VA_ARGS__)
+-#define alert(fmt, ...) printk(KERN_ALERT "%s %s:%d: Alert: " fmt "\n", \
+- TPM_MODULE_NAME, __FILE__, __LINE__, ## __VA_ARGS__)
++#define info(fmt, ...) printf("%s:%d: Info: " fmt "\n", \
++ __FILE__, __LINE__, ## __VA_ARGS__)
++#define error(fmt, ...) printf("%s:%d: Error: " fmt "\n", \
++ __FILE__, __LINE__, ## __VA_ARGS__)
++#define alert(fmt, ...) printf("%s:%d: Alert: " fmt "\n", \
++ __FILE__, __LINE__, ## __VA_ARGS__)
+
+ /* memory allocation */
+
+ static inline void *tpm_malloc(size_t size)
+ {
+- return kmalloc(size, GFP_KERNEL);
++ return malloc(size);
+ }
+
+ static inline void tpm_free(const void *ptr)
+ {
+- if (ptr != NULL) kfree(ptr);
++ if (ptr != NULL) free( (void *) ptr);
+ }
+
+ /* random numbers */
+
++//FIXME;
++void get_random_bytes(void *buf, int nbytes);
++
+ static inline void tpm_get_random_bytes(void *buf, int nbytes)
+ {
+ get_random_bytes(buf, nbytes);
+@@ -84,9 +93,9 @@ uint64_t tpm_get_ticks(void);
+ #define CPU_TO_LE16(x) __cpu_to_le16(x)
+
+ #define BE64_TO_CPU(x) __be64_to_cpu(x)
+-#define LE64_TO_CPU(x) __be64_to_cpu(x)
++#define LE64_TO_CPU(x) __le64_to_cpu(x)
+ #define BE32_TO_CPU(x) __be32_to_cpu(x)
+-#define LE32_TO_CPU(x) __be32_to_cpu(x)
++#define LE32_TO_CPU(x) __le32_to_cpu(x)
+ #define BE16_TO_CPU(x) __be16_to_cpu(x)
+ #define LE16_TO_CPU(x) __le16_to_cpu(x)
+
+diff -uprN orig/tpm_emulator-0.2/tpm/tpm_audit.c vtpm/tpm/tpm_audit.c
+--- orig/tpm_emulator-0.2/tpm/tpm_audit.c 2005-08-17 10:58:36.000000000
-0700
++++ vtpm/tpm/tpm_audit.c 2005-08-17 10:55:52.000000000 -0700
+@@ -1,6 +1,7 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
+ * Swiss Federal Institute of Technology (ETH) Zurich
++ * Copyright (C) 2005 INTEL Corp
+ *
+ * This module is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+@@ -45,14 +46,14 @@ void tpm_audit_request(TPM_COMMAND_CODE
+ tpmData.permanent.data.auditMonotonicCounter++;
+ }
+ /* update audit digest */
+- *((UINT16*)&buf[0]) = cpu_to_be16(TPM_TAG_AUDIT_EVENT_IN);
+- *((UINT32*)&buf[2]) = cpu_to_be32(ordinal);
++ *((UINT16*)&buf[0]) = CPU_TO_BE16(TPM_TAG_AUDIT_EVENT_IN);
++ *((UINT32*)&buf[2]) = CPU_TO_BE32(ordinal);
+ sha1_init(&sha1_ctx);
+ sha1_update(&sha1_ctx, req->param, req->paramSize);
+ sha1_final(&sha1_ctx, &buf[6]);
+- *((UINT16*)&buf[26]) = cpu_to_be16(TPM_TAG_COUNTER_VALUE);
++ *((UINT16*)&buf[26]) = CPU_TO_BE16(TPM_TAG_COUNTER_VALUE);
+ memset(&buf[30], 0, 4);
+- *((UINT32*)&buf[34]) =
cpu_to_be32(tpmData.permanent.data.auditMonotonicCounter);
++ *((UINT32*)&buf[34]) =
CPU_TO_BE32(tpmData.permanent.data.auditMonotonicCounter);
+ sha1_init(&sha1_ctx);
+ sha1_update(&sha1_ctx, tpmData.stany.data.auditDigest.digest,
+ sizeof(TPM_DIGEST));
+@@ -70,15 +71,15 @@ void tpm_audit_response(TPM_COMMAND_CODE
+ && (AUDIT_STATUS[ord / 8] & (1 << (ord & 0x07)))) {
+ info("tpm_audit_response()");
+ /* update audit digest */
+- *((UINT16*)&buf[0]) = cpu_to_be16(TPM_TAG_AUDIT_EVENT_OUT);
+- *((UINT32*)&buf[2]) = cpu_to_be32(ordinal);
++ *((UINT16*)&buf[0]) = CPU_TO_BE16(TPM_TAG_AUDIT_EVENT_OUT);
++ *((UINT32*)&buf[2]) = CPU_TO_BE32(ordinal);
+ sha1_init(&sha1_ctx);
+ sha1_update(&sha1_ctx, rsp->param, rsp->paramSize);
+ sha1_final(&sha1_ctx, &buf[6]);
+- *((UINT16*)&buf[26]) = cpu_to_be16(TPM_TAG_COUNTER_VALUE);
++ *((UINT16*)&buf[26]) = CPU_TO_BE16(TPM_TAG_COUNTER_VALUE);
+ memset(&buf[30], 0, 4);
+- *((UINT32*)&buf[34]) =
cpu_to_be32(tpmData.permanent.data.auditMonotonicCounter);
+- *((UINT32*)&buf[34]) = cpu_to_be32(rsp->result);
++ *((UINT32*)&buf[34]) =
CPU_TO_BE32(tpmData.permanent.data.auditMonotonicCounter);
++ *((UINT32*)&buf[34]) = CPU_TO_BE32(rsp->result);
+ sha1_init(&sha1_ctx);
+ sha1_update(&sha1_ctx, tpmData.stany.data.auditDigest.digest,
+ sizeof(TPM_DIGEST));
+@@ -158,7 +159,7 @@ TPM_RESULT TPM_GetAuditDigestSigned(TPM_
+ }
+ memcpy(&buf[0], "\x05\x00ADIG", 6);
+ memcpy(&buf[6], antiReplay->nonce, 20);
+- *(UINT32*)&buf[26] = cpu_to_be32(buf_size - 30);
++ *(UINT32*)&buf[26] = CPU_TO_BE32(buf_size - 30);
+ memcpy(&buf[30], auditDigest->digest, 20);
+ ptr = &buf[50];
+ len = buf_size - 50;
+@@ -198,4 +199,3 @@ TPM_RESULT TPM_SetOrdinalAuditStatus(TPM
+ }
+ return TPM_SUCCESS;
+ }
+-
+diff -uprN orig/tpm_emulator-0.2/tpm/tpm_authorization.c
vtpm/tpm/tpm_authorization.c
+--- orig/tpm_emulator-0.2/tpm/tpm_authorization.c 2005-08-17
10:58:36.000000000 -0700
++++ vtpm/tpm/tpm_authorization.c 2005-08-17 10:55:52.000000000 -0700
+@@ -1,6 +1,7 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
+ * Swiss Federal Institute of Technology (ETH) Zurich
++ * Copyright (C) 2005 INTEL Corp
+ *
+ * This module is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+@@ -268,7 +269,7 @@ TPM_RESULT tpm_verify_auth(TPM_AUTH *aut
+ {
+ hmac_ctx_t ctx;
+ TPM_SESSION_DATA *session;
+- UINT32 auth_handle = cpu_to_be32(auth->authHandle);
++ UINT32 auth_handle = CPU_TO_BE32(auth->authHandle);
+
+ info("tpm_verify_auth(%08x)", auth->authHandle);
+ /* get dedicated authorization session */
+@@ -316,5 +317,3 @@ void tpm_decrypt_auth_secret(TPM_ENCAUTH
+ for (i = 0; i < sizeof(TPM_SECRET); i++)
+ plainAuth[i] ^= encAuth[i];
+ }
+-
+-
+diff -uprN orig/tpm_emulator-0.2/tpm/tpm_capability.c vtpm/tpm/tpm_capability.c
+--- orig/tpm_emulator-0.2/tpm/tpm_capability.c 2005-08-17 10:58:36.000000000
-0700
++++ vtpm/tpm/tpm_capability.c 2005-08-17 10:55:52.000000000 -0700
+@@ -1,6 +1,7 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
+ * Swiss Federal Institute of Technology (ETH) Zurich
++ * Copyright (C) 2005 INTEL Corp
+ *
+ * This module is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+@@ -398,7 +399,7 @@ TPM_RESULT TPM_GetCapability(TPM_CAPABIL
+
+ case TPM_CAP_KEY_HANDLE:
+ debug("[TPM_CAP_KEY_HANDLE]");
+- subCapSize = cpu_to_be32(TPM_RT_KEY);
++ subCapSize = CPU_TO_BE32(TPM_RT_KEY);
+ return cap_handle(4, (BYTE*)&subCapSize, respSize, resp);
+
+ case TPM_CAP_CHECK_LOADED:
+@@ -472,4 +473,3 @@ TPM_RESULT TPM_GetCapability(TPM_CAPABIL
+ return TPM_BAD_MODE;
+ }
+ }
+-
+diff -uprN orig/tpm_emulator-0.2/tpm/tpm_cmd_handler.c
vtpm/tpm/tpm_cmd_handler.c
+--- orig/tpm_emulator-0.2/tpm/tpm_cmd_handler.c 2005-08-17
10:58:36.000000000 -0700
++++ vtpm/tpm/tpm_cmd_handler.c 2005-08-17 10:55:52.000000000 -0700
+@@ -1,6 +1,7 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
+ * Swiss Federal Institute of Technology (ETH) Zurich
++ * Copyright (C) 2005 INTEL Corp
+ *
+ * This module is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+@@ -26,7 +27,7 @@ static void tpm_compute_in_param_digest(
+ {
+ sha1_ctx_t sha1;
+ UINT32 offset;
+- UINT32 ord = cpu_to_be32(req->ordinal);
++ UINT32 ord = CPU_TO_BE32(req->ordinal);
+
+ /* skip all key-handles at the beginning */
+ switch (req->ordinal) {
+@@ -82,8 +83,8 @@ static void tpm_compute_in_param_digest(
+ static void tpm_compute_out_param_digest(TPM_COMMAND_CODE ordinal,
TPM_RESPONSE *rsp)
+ {
+ sha1_ctx_t sha1;
+- UINT32 res = cpu_to_be32(rsp->result);
+- UINT32 ord = cpu_to_be32(ordinal);
++ UINT32 res = CPU_TO_BE32(rsp->result);
++ UINT32 ord = CPU_TO_BE32(ordinal);
+
+ /* compute SHA1 hash */
+ sha1_init(&sha1);
+@@ -3081,7 +3082,7 @@ static void tpm_setup_rsp_auth(TPM_COMMA
+ hmac_update(&hmac, rsp->auth2->digest, sizeof(rsp->auth2->digest));
+ #if 0
+ if (tpm_get_auth(rsp->auth2->authHandle)->type == TPM_ST_OIAP) {
+- UINT32 handle = cpu_to_be32(rsp->auth2->authHandle);
++ UINT32 handle = CPU_TO_BE32(rsp->auth2->authHandle);
+ hmac_update(&hmac, (BYTE*)&handle, 4);
+ }
+ #endif
+@@ -3096,7 +3097,7 @@ static void tpm_setup_rsp_auth(TPM_COMMA
+ hmac_update(&hmac, rsp->auth1->digest, sizeof(rsp->auth1->digest));
+ #if 0
+ if (tpm_get_auth(rsp->auth1->authHandle)->type == TPM_ST_OIAP) {
+- UINT32 handle = cpu_to_be32(rsp->auth1->authHandle);
++ UINT32 handle = CPU_TO_BE32(rsp->auth1->authHandle);
+ hmac_update(&hmac, (BYTE*)&handle, 4);
+ }
+ #endif
+@@ -3179,7 +3180,9 @@ extern const char *tpm_error_to_string(T
+ static void tpm_execute_command(TPM_REQUEST *req, TPM_RESPONSE *rsp)
+ {
+ TPM_RESULT res;
+-
++
++ req->tag = (BYTE) req->tag; // VIN HACK!!!
++
+ /* setup authorisation as well as response tag and size */
+ memset(rsp, 0, sizeof(*rsp));
+ switch (req->tag) {
+@@ -3878,4 +3881,3 @@ int tpm_handle_command(const uint8_t *in
+ tpm_free(rsp.param);
+ return 0;
+ }
+-
+diff -uprN orig/tpm_emulator-0.2/tpm/tpm_crypto.c vtpm/tpm/tpm_crypto.c
+--- orig/tpm_emulator-0.2/tpm/tpm_crypto.c 2005-08-17 10:58:36.000000000
-0700
++++ vtpm/tpm/tpm_crypto.c 2005-08-17 10:55:52.000000000 -0700
+@@ -1,6 +1,7 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
+ * Swiss Federal Institute of Technology (ETH) Zurich
++ * Copyright (C) 2005 INTEL Corp
+ *
+ * This module is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+@@ -106,7 +107,7 @@ TPM_RESULT tpm_sign(TPM_KEY_DATA *key, T
+ /* setup TPM_SIGN_INFO structure */
+ memcpy(&buf[0], "\x05\x00SIGN", 6);
+ memcpy(&buf[6], auth->nonceOdd.nonce, 20);
+- *(UINT32*)&buf[26] = cpu_to_be32(areaToSignSize);
++ *(UINT32*)&buf[26] = CPU_TO_BE32(areaToSignSize);
+ memcpy(&buf[30], areaToSign, areaToSignSize);
+ if (rsa_sign(&key->key, RSA_SSA_PKCS1_SHA1,
+ buf, areaToSignSize + 30, *sig)) {
+@@ -379,4 +380,3 @@ TPM_RESULT TPM_CertifyKey2(TPM_KEY_HANDL
+ }
+ return TPM_SUCCESS;
+ }
+-
+diff -uprN orig/tpm_emulator-0.2/tpm/tpm_data.c vtpm/tpm/tpm_data.c
+--- orig/tpm_emulator-0.2/tpm/tpm_data.c 2005-08-17 10:58:36.000000000
-0700
++++ vtpm/tpm/tpm_data.c 2005-08-17 10:55:52.000000000 -0700
+@@ -1,6 +1,7 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
+ * Swiss Federal Institute of Technology (ETH) Zurich
++ * Copyright (C) 2005 INTEL Corp
+ *
+ * This module is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+@@ -15,9 +16,15 @@
+ * $Id: tpm_data.c 9 2005-04-26 18:15:31Z mast $
+ */
+
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <fcntl.h>
++#include <unistd.h>
++
+ #include "tpm_emulator.h"
+ #include "tpm_structures.h"
+ #include "tpm_marshalling.h"
++#include "vtpm_manager.h"
+
+ TPM_DATA tpmData;
+
+@@ -28,6 +35,7 @@ BOOL tpm_get_physical_presence(void)
+
+ void tpm_init_data(void)
+ {
++#ifndef TPM_GENERATE_EK
+ /* endorsement key */
+ uint8_t ek_n[] = "\xa8\xdb\xa9\x42\xa8\xf3\xb8\x06\x85\x90\x76\x93\xad\xf7"
+ "\x74\xec\x3f\xd3\x3d\x9d\xe8\x2e\xff\x15\xed\x0e\xce\x5f\x93"
+@@ -66,6 +74,8 @@ void tpm_init_data(void)
+ "\xd1\xc0\x8b\x5b\xa2\x2e\xa7\x15\xca\x50\x75\x10\x48\x9c\x2b"
+ "\x18\xb9\x67\x8f\x5d\x64\xc3\x28\x9f\x2f\x16\x2f\x08\xda\x47"
+ "\xec\x86\x43\x0c\x80\x99\x07\x34\x0f";
++#endif
++
+ int i;
+ /* reset all data to NULL, FALSE or 0 */
+ memset(&tpmData, 0, sizeof(tpmData));
+@@ -85,6 +95,10 @@ void tpm_init_data(void)
+ tpmData.permanent.data.version.revMinor = VERSION_MINOR;
+ /* setup PCR attributes */
+ for (i = 0; i < TPM_NUM_PCR; i++) {
++ int j;
++ for (j=0; j < TPM_NUM_LOCALITY; j++) {
++ tpmData.permanent.data.pcrAttrib[i].pcrExtendLocal[j] = TRUE;
++ }
+ tpmData.permanent.data.pcrAttrib[i].pcrReset = TRUE;
+ }
+ /* set tick type */
+@@ -115,49 +129,235 @@ void tpm_release_data(void)
+
+ #ifdef TPM_STORE_TO_FILE
+
+-#include <linux/fs.h>
+-#include <linux/unistd.h>
+-#include <asm/uaccess.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <fcntl.h>
++
++ static int vtpm_tx_fh=-1, vtpm_rx_fh=-1;
+
+-#define TPM_STORAGE_FILE "/var/tpm/tpm_emulator-1.2." STR(VERSION_MAJOR) "."
STR(VERSION_MINOR)
++#ifdef VTPM_MUTLI_VM
++ #define DEV_FE "/dev/tpm"
++#else
++ #define VTPM_RX_FIFO_D "/var/vtpm/fifos/vtpm-to-%d.fifo"
++ #define VTPM_TX_FIFO "/var/vtpm/fifos/vtpm-from-all.fifo"
++
++ extern int dmi_id;
++ static char *vtpm_rx_name=NULL;
++#endif
+
+ static int write_to_file(uint8_t *data, size_t data_length)
+ {
+- int res;
+- struct file *fp;
+- mm_segment_t old_fs = get_fs();
+- fp = filp_open(TPM_STORAGE_FILE, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR |
S_IWUSR);
+- if (IS_ERR(fp)) return -1;
+- set_fs(get_ds());
+- res = fp->f_op->write(fp, data, data_length, &fp->f_pos);
+- set_fs(old_fs);
+- filp_close(fp, NULL);
+- return (res == data_length) ? 0 : -1;
++ int res, out_data_size, in_header_size;
++ BYTE *ptr, *out_data, *in_header;
++ UINT32 result, len, in_rsp_size;
++ UINT16 tag = VTPM_TAG_REQ;
++
++ printf("Saving NVM\n");
++ if (vtpm_tx_fh < 0) {
++#ifdef VTPM_MUTLI_VM
++ vtpm_tx_fh = open(DEV_FE, O_RDWR);
++#else
++ vtpm_tx_fh = open(VTPM_TX_FIFO, O_WRONLY);
++#endif
++ }
++
++ if (vtpm_tx_fh < 0) {
++ return -1;
++ }
++
++ // Send request to VTPM Manager to encrypt data
++#ifdef VTPM_MUTLI_VM
++ out_data_size = len = VTPM_COMMAND_HEADER_SIZE_CLT + data_length;
++#else
++ out_data_size = len = VTPM_COMMAND_HEADER_SIZE_SRV + data_length;
++#endif
++
++ out_data = ptr = (BYTE *) malloc(len);
++
++ if (ptr == NULL
++#ifndef VTPM_MUTLI_VM
++ || tpm_marshal_UINT32(&ptr, &len, dmi_id)
++#endif
++ || tpm_marshal_UINT16(&ptr, &len, tag)
++#ifdef VTPM_MUTLI_VM
++ || tpm_marshal_UINT32(&ptr, &len, out_data_size)
++#else
++ || tpm_marshal_UINT32(&ptr, &len, out_data_size - sizeof(uint32_t))
++#endif
++ || tpm_marshal_UINT32(&ptr, &len, VTPM_ORD_SAVENVM)
++ || tpm_marshal_BYTE_ARRAY(&ptr, &len, data, data_length)) {
++ free(out_data);
++ return -1;
++ }
++
++ printf("\tSending SaveNVM Command.\n");
++ res = write(vtpm_tx_fh, out_data, out_data_size);
++ free(out_data);
++ if (res != out_data_size) return -1;
++
++ if (vtpm_rx_fh < 0) {
++#ifdef VTPM_MUTLI_VM
++ vtpm_rx_fh = vtpm_tx_fh
++#else
++ if (vtpm_rx_name == NULL) {
++ vtpm_rx_name = malloc(10 + strlen(VTPM_RX_FIFO_D));
++ sprintf(vtpm_rx_name, VTPM_RX_FIFO_D, (uint32_t) dmi_id);
++ }
++ vtpm_rx_fh = open(vtpm_rx_name, O_RDONLY);
++#endif
++ }
++
++ if (vtpm_rx_fh < 0) {
++ return -1;
++ }
++
++ // Read Header of response so we can get the size & status
++#ifdef VTPM_MUTLI_VM
++ in_header_size = len = VTPM_COMMAND_HEADER_SIZE_CLT;
++#else
++ in_header_size = len = VTPM_COMMAND_HEADER_SIZE_SRV;
++#endif
++ in_header = ptr = malloc(in_header_size);
++
++ printf("\tReading SaveNVM header.\n");
++ res = read(vtpm_rx_fh, in_header, in_header_size);
++
++ if ( (res != in_header_size)
++#ifndef VTPM_MUTLI_VM
++ || tpm_unmarshal_UINT32(&ptr, &len, (UINT32*)&dmi_id)
++#endif
++ || tpm_unmarshal_UINT16(&ptr, &len, &tag)
++ || tpm_unmarshal_UINT32(&ptr, &len, &in_rsp_size)
++ || tpm_unmarshal_UINT32(&ptr, &len, &result) ) {
++ free(in_header);
++ return -1;
++ }
++ free(in_header);
++
++ if (result != VTPM_SUCCESS) {
++ return -1;
++ }
++
++#ifdef VTPM_MUTLI_VM
++ close(vtpm_tx_fh); close(vtpm_rx_fh);
++#endif
++
++ printf("\tFinishing up SaveNVM\n");
++ return (0);
+ }
+
+ static int read_from_file(uint8_t **data, size_t *data_length)
+ {
+- int res;
+- struct file *fp;
+- mm_segment_t old_fs = get_fs();
+- fp = filp_open(TPM_STORAGE_FILE, O_RDONLY, 0);
+- if (IS_ERR(fp)) return -1;
+- *data_length = (size_t)fp->f_dentry->d_inode->i_size;
+- /* *data_length = i_size_read(fp->f_dentry->d_inode); */
+- *data = tpm_malloc(*data_length);
+- if (*data == NULL) {
+- filp_close(fp, NULL);
++ int res, out_data_size, in_header_size;
++ uint8_t *ptr, *out_data, *in_header;
++ UINT16 tag = VTPM_TAG_REQ;
++ UINT32 len, in_rsp_size, result;
++#ifdef VTPM_MUTLI_VM
++ int vtpm_rx_fh, vtpm_tx_fh;
++#endif
++
++ printf("Loading NVM.\n");
++ if (vtpm_tx_fh < 0) {
++#ifdef VTPM_MUTLI_VM
++ vtpm_tx_fh = open(DEV_FE, O_RDWR);
++#else
++ vtpm_tx_fh = open(VTPM_TX_FIFO, O_WRONLY);
++#endif
++ }
++
++ if (vtpm_tx_fh < 0) {
++ return -1;
++ }
++
++ // Send request to VTPM Manager to encrypt data
++#ifdef VTPM_MUTLI_VM
++ out_data_size = len = VTPM_COMMAND_HEADER_SIZE_CLT;
++#else
++ out_data_size = len = VTPM_COMMAND_HEADER_SIZE_SRV;
++#endif
++ out_data = ptr = (BYTE *) malloc(len);
++
++ if (ptr == NULL
++#ifndef VTPM_MUTLI_VM
++ || tpm_marshal_UINT32(&ptr, &len, dmi_id)
++#endif
++ || tpm_marshal_UINT16(&ptr, &len, tag)
++#ifdef VTPM_MUTLI_VM
++ || tpm_marshal_UINT32(&ptr, &len, out_data_size)
++#else
++ || tpm_marshal_UINT32(&ptr, &len, out_data_size - sizeof(uint32_t))
++#endif
++ || tpm_marshal_UINT32(&ptr, &len, VTPM_ORD_LOADNVM)) {
++ free(out_data);
+ return -1;
+ }
+- set_fs(get_ds());
+- res = fp->f_op->read(fp, *data, *data_length, &fp->f_pos);
+- set_fs(old_fs);
+- filp_close(fp, NULL);
++
++ printf("\tSending LoadNVM command\n");
++ res = write(vtpm_tx_fh, out_data, out_data_size);
++ free(out_data);
++ if (res != out_data_size) return -1;
++
++ if (vtpm_rx_fh < 0) {
++#ifdef VTPM_MUTLI_VM
++ vtpm_rx_fh = vtpm_tx_fh;
++#else
++ if (vtpm_rx_name == NULL) {
++ vtpm_rx_name = malloc(10 + strlen(VTPM_RX_FIFO_D));
++ sprintf(vtpm_rx_name, VTPM_RX_FIFO_D, (uint32_t) dmi_id);
++ }
++ vtpm_rx_fh = open(vtpm_rx_name, O_RDONLY);
++#endif
++ }
++
++ if (vtpm_rx_fh < 0) {
++ return -1;
++ }
++
++ // Read Header of response so we can get the size & status
++#ifdef VTPM_MUTLI_VM
++ in_header_size = len = VTPM_COMMAND_HEADER_SIZE_CLT;
++#else
++ in_header_size = len = VTPM_COMMAND_HEADER_SIZE_SRV;
++#endif
++ in_header = ptr = malloc(in_header_size);
++
++ printf("\tReading LoadNVM header\n");
++ res = read(vtpm_rx_fh, in_header, in_header_size);
++
++ if ( (res != in_header_size)
++#ifndef VTPM_MUTLI_VM
++ || tpm_unmarshal_UINT32(&ptr, &len, (UINT32*)&dmi_id)
++#endif
++ || tpm_unmarshal_UINT16(&ptr, &len, &tag)
++ || tpm_unmarshal_UINT32(&ptr, &len, &in_rsp_size)
++ || tpm_unmarshal_UINT32(&ptr, &len, &result) ) {
++ free(in_header);
++ return -1;
++ }
++ free(in_header);
++
++ if (result != VTPM_SUCCESS) {
++ return -1;
++ }
++
++ // Read Encrypted data from VTPM Manager
++ *data_length = in_rsp_size - VTPM_COMMAND_HEADER_SIZE_CLT;
++ *data = (uint8_t *) malloc(*data_length);
++
++ printf("\tReading clear data from LoadNVM.\n");
++ res = read(vtpm_rx_fh, *data, *data_length);
++#ifdef VTPM_MUTLI_VM
++ close(vtpm_rx_fh);close(vtpm_tx_fh);
++#endif
++
++ printf("\tReturing from loading NVM\n");
+ if (res != *data_length) {
+- tpm_free(*data);
+- return -1;
++ free(*data);
++ return -1;
++ } else {
++ return 0;
+ }
+- return 0;
++
+ }
+
+ #else
+@@ -231,7 +431,6 @@ int tpm_restore_permanent_data(void)
+
+ int tpm_erase_permanent_data(void)
+ {
+- int res = write_to_file("", 0);
++ int res = write_to_file((uint8_t*)"", 0);
+ return res;
+ }
+-
+diff -uprN orig/tpm_emulator-0.2/tpm/tpm_deprecated.c vtpm/tpm/tpm_deprecated.c
+--- orig/tpm_emulator-0.2/tpm/tpm_deprecated.c 2005-08-17 10:58:36.000000000
-0700
++++ vtpm/tpm/tpm_deprecated.c 2005-08-17 10:55:52.000000000 -0700
+@@ -1,6 +1,7 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
+ * Swiss Federal Institute of Technology (ETH) Zurich
++ * Copyright (C) 2005 INTEL Corp
+ *
+ * This module is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+@@ -50,7 +51,7 @@ TPM_RESULT TPM_SaveKeyContext(TPM_KEY_HA
+ BYTE *ptr;
+ UINT32 len;
+ info("TPM_SaveKeyContext()");
+- res = TPM_SaveContext(keyHandle, TPM_RT_KEY, "SaveKeyContext..",
++ res = TPM_SaveContext(keyHandle, TPM_RT_KEY, (BYTE*)"SaveKeyContext..",
+ keyContextSize, &contextBlob);
+ if (res != TPM_SUCCESS) return res;
+ len = *keyContextSize;
+@@ -82,7 +83,7 @@ TPM_RESULT TPM_SaveAuthContext(TPM_AUTHH
+ BYTE *ptr;
+ UINT32 len;
+ info("TPM_SaveAuthContext()");
+- res = TPM_SaveContext(authHandle, TPM_RT_KEY, "SaveAuthContext.",
++ res = TPM_SaveContext(authHandle, TPM_RT_KEY, (BYTE*)"SaveAuthContext.",
+ authContextSize, &contextBlob);
+ if (res != TPM_SUCCESS) return res;
+ len = *authContextSize;
+diff -uprN orig/tpm_emulator-0.2/tpm/tpm_emulator.h vtpm/tpm/tpm_emulator.h
+--- orig/tpm_emulator-0.2/tpm/tpm_emulator.h 2005-08-17 10:58:36.000000000
-0700
++++ vtpm/tpm/tpm_emulator.h 2005-08-17 10:55:52.000000000 -0700
+@@ -1,5 +1,6 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
++ * Copyright (C) 2005 INTEL Corp
+ *
+ * This module is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+@@ -22,7 +23,8 @@
+ /* TPM configuration */
+ #define TPM_STORE_TO_FILE 1
+ #undef TPM_STRONG_PERSISTENCE
+-#undef TPM_GENERATE_EK
++//#undef TPM_GENERATE_EK
++#define TPM_GENERATE_EK
+
+ /**
+ * tpm_emulator_init - initialises and starts the TPM emulator
+diff -uprN orig/tpm_emulator-0.2/tpm/tpm_integrity.c vtpm/tpm/tpm_integrity.c
+--- orig/tpm_emulator-0.2/tpm/tpm_integrity.c 2005-08-17 10:58:36.000000000
-0700
++++ vtpm/tpm/tpm_integrity.c 2005-08-17 10:55:52.000000000 -0700
+@@ -1,6 +1,7 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
+ * Swiss Federal Institute of Technology (ETH) Zurich
++ * Copyright (C) 2005 INTEL Corp
+ *
+ * This module is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+@@ -194,4 +195,3 @@ TPM_RESULT tpm_verify_pcr(TPM_KEY_DATA *
+ }
+ return TPM_SUCCESS;
+ }
+-
+diff -uprN orig/tpm_emulator-0.2/tpm/tpm_structures.h vtpm/tpm/tpm_structures.h
+--- orig/tpm_emulator-0.2/tpm/tpm_structures.h 2005-08-17 10:58:36.000000000
-0700
++++ vtpm/tpm/tpm_structures.h 2005-08-17 10:55:52.000000000 -0700
+@@ -1,6 +1,7 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
+ * Swiss Federal Institute of Technology (ETH) Zurich
++ * Copyright (C) 2005 INTEL Corp
+ *
+ * This module is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+@@ -18,7 +19,7 @@
+ #ifndef _TPM_STRUCTURES_H_
+ #define _TPM_STRUCTURES_H_
+
+-#include <linux/types.h>
++//#include <linux/types.h>
+ #include "crypto/rsa.h"
+
+ /*
+diff -uprN orig/tpm_emulator-0.2/tpm/tpm_testing.c vtpm/tpm/tpm_testing.c
+--- orig/tpm_emulator-0.2/tpm/tpm_testing.c 2005-08-17 10:58:36.000000000
-0700
++++ vtpm/tpm/tpm_testing.c 2005-08-17 10:55:52.000000000 -0700
+@@ -1,6 +1,7 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
+ * Swiss Federal Institute of Technology (ETH) Zurich
++ * Copyright (C) 2005 INTEL Corp
+ *
+ * This module is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+@@ -95,24 +96,24 @@ static int tpm_test_sha1(void)
+ struct {
+ uint8_t *data; uint32_t repetitions; uint8_t *digest;
+ } test_cases[] = {{
+- "abc", 1,
+-
"\xA9\x99\x3E\x36\x47\x06\x81\x6A\xBA\x3E\x25\x71\x78\x50\xC2\x6C\x9C\xD0\xD8\x9D"
++ (uint8_t*)"abc", 1,
++
(uint8_t*)"\xA9\x99\x3E\x36\x47\x06\x81\x6A\xBA\x3E\x25\x71\x78\x50\xC2\x6C\x9C\xD0\xD8\x9D"
+ }, {
+- "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1,
+-
"\x84\x98\x3E\x44\x1C\x3B\xD2\x6E\xBA\xAE\x4A\xA1\xF9\x51\x29\xE5\xE5\x46\x70\xF1"
++ (uint8_t*)"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1,
++
(uint8_t*)"\x84\x98\x3E\x44\x1C\x3B\xD2\x6E\xBA\xAE\x4A\xA1\xF9\x51\x29\xE5\xE5\x46\x70\xF1"
+ }, {
+- "a", 1000000,
+-
"\x34\xAA\x97\x3C\xD4\xC4\xDA\xA4\xF6\x1E\xEB\x2B\xDB\xAD\x27\x31\x65\x34\x01\x6F"
++ (uint8_t*)"a", 1000000,
++
(uint8_t*)"\x34\xAA\x97\x3C\xD4\xC4\xDA\xA4\xF6\x1E\xEB\x2B\xDB\xAD\x27\x31\x65\x34\x01\x6F"
+ }, {
+- "0123456701234567012345670123456701234567012345670123456701234567", 10,
+-
"\xDE\xA3\x56\xA2\xCD\xDD\x90\xC7\xA7\xEC\xED\xC5\xEB\xB5\x63\x93\x4F\x46\x04\x52"
++
(uint8_t*)"0123456701234567012345670123456701234567012345670123456701234567",
10,
++
(uint8_t*)"\xDE\xA3\x56\xA2\xCD\xDD\x90\xC7\xA7\xEC\xED\xC5\xEB\xB5\x63\x93\x4F\x46\x04\x52"
+ }};
+
+ debug("tpm_test_sha1()");
+ for (i = 0; i < sizeof(test_cases) / sizeof(test_cases[0]); i++) {
+ sha1_init(&ctx);
+ for (j = 0; j < test_cases[i].repetitions; j++)
+- sha1_update(&ctx, test_cases[i].data, strlen(test_cases[i].data));
++ sha1_update(&ctx, test_cases[i].data,
strlen((char*)test_cases[i].data));
+ sha1_final(&ctx, digest);
+ if (memcmp(digest, test_cases[i].digest, SHA1_DIGEST_LENGTH) != 0) return
-1;
+ }
+@@ -128,41 +129,41 @@ static int tpm_test_hmac(void)
+ struct {
+ uint8_t *key, key_len, *data, data_len, *digest;
+ } test_cases[] = {{
+- "\x0b", 20, "Hi There", 8,
+-
"\xb6\x17\x31\x86\x55\x05\x72\x64\xe2\x8b\xc0\xb6\xfb\x37\x8c\x8e\xf1\x46\xbe\x00"
++ (uint8_t*)"\x0b", 20, (uint8_t*)"Hi There", 8,
++
(uint8_t*)"\xb6\x17\x31\x86\x55\x05\x72\x64\xe2\x8b\xc0\xb6\xfb\x37\x8c\x8e\xf1\x46\xbe\x00"
+ }, {
+- "Jefe", 4, "what do ya want for nothing?", 28,
+-
"\xef\xfc\xdf\x6a\xe5\xeb\x2f\xa2\xd2\x74\x16\xd5\xf1\x84\xdf\x9c\x25\x9a\x7c\x79"
++ (uint8_t*)"Jefe", 4, (uint8_t*)"what do ya want for nothing?", 28,
++
(uint8_t*)"\xef\xfc\xdf\x6a\xe5\xeb\x2f\xa2\xd2\x74\x16\xd5\xf1\x84\xdf\x9c\x25\x9a\x7c\x79"
+ }, {
+- "\xaa", 20, "\xdd", 50,
+-
"\x12\x5d\x73\x42\xb9\xac\x11\xcd\x91\xa3\x9a\xf4\x8a\xa1\x7b\x4f\x63\xf1\x75\xd3"
++ (uint8_t*)"\xaa", 20, (uint8_t*)"\xdd", 50,
++
(uint8_t*)"\x12\x5d\x73\x42\xb9\xac\x11\xcd\x91\xa3\x9a\xf4\x8a\xa1\x7b\x4f\x63\xf1\x75\xd3"
+ }, {
+-
"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14"
+- "\x15\x16\x17\x18\x19", 25, "\xcd", 50,
+-
"\x4c\x90\x07\xf4\x02\x62\x50\xc6\xbc\x84\x14\xf9\xbf\x50\xc8\x6c\x2d\x72\x35\xda"
++
(uint8_t*)"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14"
++ "\x15\x16\x17\x18\x19", 25, (uint8_t*)"\xcd", 50,
++
(uint8_t*)"\x4c\x90\x07\xf4\x02\x62\x50\xc6\xbc\x84\x14\xf9\xbf\x50\xc8\x6c\x2d\x72\x35\xda"
+ }, {
+- "\x0c", 20, "Test With Truncation", 20,
+-
"\x4c\x1a\x03\x42\x4b\x55\xe0\x7f\xe7\xf2\x7b\xe1\xd5\x8b\xb9\x32\x4a\x9a\x5a\x04"
++ (uint8_t*)"\x0c", 20, (uint8_t*)"Test With Truncation", 20,
++
(uint8_t*)"\x4c\x1a\x03\x42\x4b\x55\xe0\x7f\xe7\xf2\x7b\xe1\xd5\x8b\xb9\x32\x4a\x9a\x5a\x04"
+ }, {
+- "\xaa", 80, "Test Using Larger Than Block-Size Key - Hash Key First", 54,
+-
"\xaa\x4a\xe5\xe1\x52\x72\xd0\x0e\x95\x70\x56\x37\xce\x8a\x3b\x55\xed\x40\x21\x12"
++ (uint8_t*)"\xaa", 80, (uint8_t*)"Test Using Larger Than Block-Size Key -
Hash Key First", 54,
++
(uint8_t*)"\xaa\x4a\xe5\xe1\x52\x72\xd0\x0e\x95\x70\x56\x37\xce\x8a\x3b\x55\xed\x40\x21\x12"
+ }, {
+- "\xaa", 80,
+- "Test Using Larger Than Block-Size Key and Larger Than One Block-Size
Data", 73,
+-
"\xe8\xe9\x9d\x0f\x45\x23\x7d\x78\x6d\x6b\xba\xa7\x96\x5c\x78\x08\xbb\xff\x1a\x91"
++ (uint8_t*)"\xaa", 80,
++ (uint8_t*)"Test Using Larger Than Block-Size Key and Larger Than One
Block-Size Data", 73,
++
(uint8_t*)"\xe8\xe9\x9d\x0f\x45\x23\x7d\x78\x6d\x6b\xba\xa7\x96\x5c\x78\x08\xbb\xff\x1a\x91"
+ }};
+
+ debug("tpm_test_hmac()");
+ for (i = 0; i < sizeof(test_cases) / sizeof(test_cases[0]); i++) {
+- if (strlen(test_cases[i].key) < test_cases[i].key_len) {
++ if (strlen((char*)test_cases[i].key) < test_cases[i].key_len) {
+ uint8_t key[test_cases[i].key_len];
+ memset(key, test_cases[i].key[0], test_cases[i].key_len);
+ hmac_init(&ctx, key, test_cases[i].key_len);
+ } else {
+ hmac_init(&ctx, test_cases[i].key, test_cases[i].key_len);
+ }
+- for (j = 0; j < test_cases[i].data_len; j += strlen(test_cases[i].data)) {
+- hmac_update(&ctx, test_cases[i].data, strlen(test_cases[i].data));
++ for (j = 0; j < test_cases[i].data_len; j +=
strlen((char*)test_cases[i].data)) {
++ hmac_update(&ctx, test_cases[i].data,
strlen((char*)test_cases[i].data));
+ }
+ hmac_final(&ctx, digest);
+ if (memcmp(digest, test_cases[i].digest, SHA1_DIGEST_LENGTH) != 0) return
-1;
+@@ -173,9 +174,9 @@ static int tpm_test_hmac(void)
+ static int tpm_test_rsa_EK(void)
+ {
+ int res = 0;
+- char *data = "RSA PKCS #1 v1.5 Test-String";
++ uint8_t *data = (uint8_t*)"RSA PKCS #1 v1.5 Test-String";
+ uint8_t buf[256];
+- size_t buf_len, data_len = strlen(data);
++ size_t buf_len, data_len = strlen((char*)data);
+ rsa_private_key_t priv_key;
+ rsa_public_key_t pub_key;
+
+diff -uprN orig/tpm_emulator-0.2/tpm/tpm_ticks.c vtpm/tpm/tpm_ticks.c
+--- orig/tpm_emulator-0.2/tpm/tpm_ticks.c 2005-08-17 10:58:36.000000000
-0700
++++ vtpm/tpm/tpm_ticks.c 2005-08-17 10:55:52.000000000 -0700
+@@ -1,6 +1,7 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
+ * Swiss Federal Institute of Technology (ETH) Zurich
++ * Copyright (C) 2005 INTEL Corp
+ *
+ * This module is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+@@ -37,9 +38,7 @@ TPM_RESULT TPM_SetTickType(TPM_TICKTYPE
+ TPM_RESULT TPM_GetTicks(TPM_CURRENT_TICKS *currentTime)
+ {
+ info("TPM_GetTicks()");
+- memcpy(currentTime, &tpmData.stany.data.currentTicks,
+- sizeof(TPM_CURRENT_TICKS));
+- return TPM_SUCCESS;
++ return TPM_DISABLED_CMD;
+ }
+
+ TPM_RESULT TPM_TickStampBlob(TPM_KEY_HANDLE keyHandle, TPM_NONCE *antiReplay,
+@@ -47,61 +46,12 @@ TPM_RESULT TPM_TickStampBlob(TPM_KEY_HAN
+ TPM_CURRENT_TICKS *currentTicks,
+ UINT32 *sigSize, BYTE **sig)
+ {
+- TPM_RESULT res;
+- TPM_KEY_DATA *key;
+- BYTE *info, *p;
+- UINT32 info_length, length;
+ info("TPM_TickStampBlob()");
+- /* get key */
+- key = tpm_get_key(keyHandle);
+- if (key == NULL) return TPM_INVALID_KEYHANDLE;
+- /* verify authorization */
+- res = tpm_verify_auth(auth1, key->usageAuth, keyHandle);
+- if (res != TPM_SUCCESS) return res;
+- if (key->keyUsage != TPM_KEY_SIGNING && key->keyUsage != TPM_KEY_LEGACY
+- && key->keyUsage != TPM_KEY_IDENTITY) return TPM_INVALID_KEYUSAGE;
+- /* get current ticks */
+- TPM_GetTicks(currentTicks);
+- /* sign data using signature scheme PKCS1_SHA1 and TPM_SIGN_INFO container
*/
+- *sigSize = key->key.size >> 3;
+- *sig = tpm_malloc(*sigSize);
+- if (*sig == NULL) return TPM_FAIL;
+- /* setup TPM_SIGN_INFO structure */
+- info_length = 30 + sizeof(TPM_DIGEST) +
sizeof_TPM_CURRENT_TICKS(currentTicks);
+- info = tpm_malloc(info_length);
+- if (info == NULL) {
+- tpm_free(*sig);
+- return TPM_FAIL;
+- }
+- memcpy(&info[0], "\x05\x00TSTP", 6);
+- memcpy(&info[6], antiReplay->nonce, 20);
+- *(UINT32*)&info[26] = cpu_to_be32(20
+- + sizeof_TPM_CURRENT_TICKS(currentTicks));
+- memcpy(&info[30], digestToStamp->digest, sizeof(TPM_DIGEST));
+- p = &info[30 + sizeof(TPM_DIGEST)];
+- length = sizeof_TPM_CURRENT_TICKS(currentTicks);
+- if (tpm_marshal_TPM_CURRENT_TICKS(&p, &length, currentTicks)
+- || rsa_sign(&key->key, RSA_SSA_PKCS1_SHA1, info, info_length, *sig)) {
+- tpm_free(*sig);
+- tpm_free(info);
+- return TPM_FAIL;
+- }
+- return TPM_SUCCESS;
++ return TPM_DISABLED_CMD;
+ }
+
+ void tpm_update_ticks(void)
+ {
+- if (tpmData.stany.data.currentTicks.tag == 0) {
+- tpmData.stany.data.currentTicks.tag = TPM_TAG_CURRENT_TICKS;
+- tpmData.stany.data.currentTicks.currentTicks += tpm_get_ticks();
+- tpmData.stany.data.currentTicks.tickType =
tpmData.permanent.data.tickType;
+- tpm_get_random_bytes(tpmData.stany.data.currentTicks.tickNonce.nonce,
+- sizeof(TPM_NONCE));
+- tpmData.stany.data.currentTicks.tickRate = 1;
+- tpmData.stany.data.currentTicks.tickSecurity = TICK_SEC_NO_CHECK;
+- } else {
+- tpmData.stany.data.currentTicks.currentTicks += tpm_get_ticks();
+- }
+ }
+
+
+diff -uprN orig/tpm_emulator-0.2/tpm/vtpm_manager.h vtpm/tpm/vtpm_manager.h
+--- orig/tpm_emulator-0.2/tpm/vtpm_manager.h 1969-12-31 16:00:00.000000000
-0800
++++ vtpm/tpm/vtpm_manager.h 2005-08-17 10:55:52.000000000 -0700
+@@ -0,0 +1,126 @@
++// ===================================================================
++//
++// Copyright (c) 2005, Intel Corp.
++// All rights reserved.
++//
++// Redistribution and use in source and binary forms, with or without
++// modification, are permitted provided that the following conditions
++// are met:
++//
++// * Redistributions of source code must retain the above copyright
++// notice, this list of conditions and the following disclaimer.
++// * Redistributions in binary form must reproduce the above
++// copyright notice, this list of conditions and the following
++// disclaimer in the documentation and/or other materials provided
++// with the distribution.
++// * Neither the name of Intel Corporation nor the names of its
++// contributors may be used to endorse or promote products derived
++// from this software without specific prior written permission.
++//
++// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
++// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
++// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
++// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
++// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++// OF THE POSSIBILITY OF SUCH DAMAGE.
++// ===================================================================
++//
++// vtpm_manager.h
++//
++// Public Interface header for VTPM Manager
++//
++// ==================================================================
++
++#ifndef __VTPM_MANAGER_H__
++#define __VTPM_MANAGER_H__
++
++#define VTPM_TAG_REQ 0x01c1
++#define VTPM_TAG_RSP 0x01c4
++#define COMMAND_BUFFER_SIZE 4096
++
++// Header sizes. Note Header MAY include the DMI
++#define VTPM_COMMAND_HEADER_SIZE_SRV ( sizeof(UINT32) + sizeof(TPM_TAG) +
sizeof(UINT32) + sizeof(TPM_COMMAND_CODE))
++#define VTPM_COMMAND_HEADER_SIZE_CLT ( sizeof(TPM_TAG) +
sizeof(UINT32) + sizeof(TPM_COMMAND_CODE))
++
++//************************ Command Codes ****************************
++#define VTPM_ORD_OPEN 1 // ULM Creates New DMI
++#define VTPM_ORD_CLOSE 2 // ULM Closes a DMI
++#define VTPM_ORD_DELETE 3 // ULM Permemently Deletes DMI
++#define VTPM_ORD_SAVENVM 4 // DMI requests Secrets Unseal
++#define VTPM_ORD_LOADNVM 5 // DMI requests Secrets Saved
++#define VTPM_ORD_TPMCOMMAND 6 // DMI issues HW TPM Command
++
++//************************ Return Codes ****************************
++#define VTPM_SUCCESS 0
++#define VTPM_FAIL 1
++#define VTPM_UNSUPPORTED 2
++#define VTPM_FORBIDDEN 3
++#define VTPM_RESTORE_CONTEXT_FAILED 4
++#define VTPM_INVALID_REQUEST 5
++
++/******************* Command Parameter API *************************
++
++VTPM Command Format
++ dmi: 4 bytes // Source of message.
++ // WARNING: This is prepended by the channel.
++ // Thus it is received by VTPM Manager,
++ // but not sent by DMI
++ tpm tag: 2 bytes
++ command size: 4 bytes // Size of command including header but not
DMI
++ ord: 4 bytes // Command ordinal above
++ parameters: size - 10 bytes // Command Parameter
++
++VTPM Response Format
++ tpm tag: 2 bytes
++ response_size: 4 bytes
++ status: 4 bytes
++ parameters: size - 10 bytes
++
++
++VTPM_Open:
++ Input Parameters:
++ Domain_type: 1 byte
++ domain_id: 4 bytes
++ instance_id: 4 bytes
++ Output Parameters:
++ None
++
++VTPM_Close
++ Input Parameters:
++ instance_id: 4 bytes
++ Output Parameters:
++ None
++
++VTPM_Delete
++ Input Parameters:
++ instance_id: 4 bytes
++ Output Parameters:
++ None
++
++VTPM_SaveNVM
++ Input Parameters:
++ data: n bytes (Header indicates size of data)
++ Output Parameters:
++ None
++
++VTPM_LoadNVM
++ Input Parameters:
++ None
++ Output Parameters:
++ data: n bytes (Header indicates size of data)
++
++VTPM_TPMCommand
++ Input Parameters:
++ TPM Command Byte Stream: n bytes
++ Output Parameters:
++ TPM Reponse Byte Stream: n bytes
++
++*********************************************************************/
++
++#endif //_VTPM_MANAGER_H_
+diff -uprN orig/tpm_emulator-0.2/tpmd.c vtpm/tpmd.c
+--- orig/tpm_emulator-0.2/tpmd.c 1969-12-31 16:00:00.000000000 -0800
++++ vtpm/tpmd.c 2005-08-17 10:55:52.000000000 -0700
+@@ -0,0 +1,207 @@
++/* Software-Based Trusted Platform Module (TPM) Emulator for Linux
++ * Copyright (C) 2005 INTEL Corp
++ *
++ * This module is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published
++ * by the Free Software Foundation; either version 2 of the License,
++ * or (at your option) any later version.
++ *
++ * This module is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <string.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <fcntl.h>
++#include <sys/time.h>
++
++#include "tpm_emulator.h"
++#include "vtpm_manager.h"
++
++#ifdef VTPM_MULTI_VM
++ #define DEV_BE "/dev/vtpm"
++#else
++ #define GUEST_RX_FIFO_D "/var/vtpm/fifos/guest-to-%d.fifo"
++ #define GUEST_TX_FIFO "/var/vtpm/fifos/guest-from-all.fifo"
++
++ int dmi_id;
++#endif
++
++#define BUFFER_SIZE 2048
++
++static uint8_t ctrl_msg[] = { 0, 0, 0, 0, // destination
++ 1, 193, // VTPM_TAG
++ 0, 0, 0, 10, // Size
++ 0, 0, 0, 0}; // TPM_SUCCESS
++
++
++static int devurandom=0;
++
++
++void get_random_bytes(void *buf, int nbytes) {
++
++ if (devurandom == 0) {
++ devurandom = open("/dev/urandom", O_RDONLY);
++ }
++
++ if (read(devurandom, buf, nbytes) != nbytes) {
++ printf("Can't get random number.\n");
++ exit(-1);
++ }
++}
++
++uint64_t tpm_get_ticks(void)
++{
++ //struct timeval tv;
++ //int gettimeofday(&tv, struct timezone *tz);
++ return 0;
++}
++
++int main(int argc, char **argv)
++{
++ uint8_t in[BUFFER_SIZE], *out, *addressed_out;
++ uint32_t out_size;
++ int in_size, written ;
++ int i, guest_id=-1;
++
++ int vtpm_tx_fh=-1, vtpm_rx_fh=-1;
++#ifdef VTPM_MULTI_VM
++ if (argc < 2) {
++ printf("Usage: tpmd clear|save|deactivated\n" );
++#else
++ if (argc < 3) {
++ printf("Usage: tpmd clear|save|deactivated vtpmid\n" );
++#endif
++ return -1;
++ }
++
++#ifndef VTPM_MULTI_VM
++ dmi_id = atoi(argv[2]);
++#endif
++
++ /* initialize TPM emulator */
++ if (!strcmp(argv[1], "clear")) {
++ printf("Initializing tpm: %s\n", argv[1]);
++ tpm_emulator_init(1);
++ } else if (!strcmp(argv[1], "save")) {
++ printf("Initializing tpm: %s\n", argv[1]);
++ tpm_emulator_init(2);
++ } else if (!strcmp(argv[1], "deactivated")) {
++ printf("Initializing tpm: %s\n", argv[1]);
++ tpm_emulator_init(3);
++ } else {
++ printf("invalid startup mode '%s'; must be 'clear', "
++ "'save' (default) or 'deactivated", argv[1]);
++ return -1;
++ }
++
++ char *guest_rx_file = malloc(10 + strlen(GUEST_RX_FIFO_D));
++ sprintf(guest_rx_file, GUEST_RX_FIFO_D, (uint32_t) dmi_id);
++
++ while (1) {
++abort_command:
++ if (vtpm_rx_fh < 0) {
++#ifdef VTPM_MUTLI_VM
++ vtpm_rx_fh = open(DEV_BE, O_RDWR);
++#else
++ vtpm_rx_fh = open(guest_rx_file, O_RDONLY);
++#endif
++ }
++
++ if (vtpm_rx_fh < 0) {
++ printf("ERROR: failed to open devices to listen to guest.\n");
++ return -1;
++ }
++
++ in_size = read(vtpm_rx_fh, in, BUFFER_SIZE);
++ if (in_size < 6) { // Magic size of minium TPM command
++ printf("Recv[%d] to small: 0x", in_size);
++ if (in_size <= 0) {
++ close(vtpm_rx_fh);
++ vtpm_rx_fh = -1;
++ goto abort_command;
++ }
++ } else {
++ printf("Recv[%d]: 0x", in_size);
++ for (i=0; i< in_size; i++)
++ printf("%x ", in[i]);
++ printf("\n");
++ }
++
++ if (guest_id == -1) {
++ guest_id = *((uint32_t *) in);
++ *((uint32_t *) ctrl_msg) = *((uint32_t *) in);
++ } else {
++ if (guest_id != *((uint32_t *) in) ) {
++ printf("WARNING: More than one guest attached\n");
++ }
++ }
++
++ if (vtpm_tx_fh < 0) {
++#ifdef VTPM_MUTLI_VM
++ vtpm_tx_fh = open(DEV_BE, O_RDWR);
++ vtpm_rx_fh = vtpm_tx_fh;
++#else
++ vtpm_tx_fh = open(GUEST_TX_FIFO, O_WRONLY);
++#endif
++ }
++
++ if (vtpm_tx_fh < 0) {
++ printf("ERROR: failed to open devices to respond to guest.\n");
++ return -1;
++ }
++
++ // Handle command, but we need to skip the identifier
++ if ( BE16_TO_CPU( ((uint16_t *) in)[2] ) == VTPM_TAG_REQ ) { // Control
message from xend
++ // This DM doesn't really care about ctrl messages. Just ACK the message
++ written = write(vtpm_tx_fh, ctrl_msg, sizeof(ctrl_msg));
++
++ if (written != sizeof(ctrl_msg)) {
++ printf("ERROR: Part of response not written %d/%d.\n", written,
sizeof(ctrl_msg));
++ } else {
++ printf("Send Ctrl Message confermation\n");
++ }
++ } else { // Message from Guest
++ if (tpm_handle_command(in + sizeof(uint32_t), in_size -
sizeof(uint32_t), &out, &out_size) != 0) {
++ printf("ERROR: Handler Failed.\n");
++ }
++
++ addressed_out = (uint8_t *) tpm_malloc(sizeof(uint32_t) + out_size);
++ *(uint32_t *) addressed_out = *(uint32_t *) in;
++ memcpy(addressed_out + sizeof(uint32_t), out, out_size);
++
++ written = write(vtpm_tx_fh, addressed_out, out_size + sizeof(uint32_t));
++
++ if (written != out_size + sizeof(uint32_t)) {
++ printf("ERROR: Part of response not written %d/%d.\n", written,
out_size);
++ for (i=0; i< out_size+ sizeof(uint32_t); i++)
++ printf("%x ", addressed_out[i]);
++ printf("\n");
++ } else {
++ printf("Sent[%d]: ", out_size + sizeof(uint32_t));
++ for (i=0; i< out_size+ sizeof(uint32_t); i++)
++ printf("%x ", addressed_out[i]);
++ printf("\n");
++ }
++ tpm_free(out);
++ tpm_free(addressed_out);
++ }
++
++ } // loop
++
++ tpm_emulator_shutdown();
++
++ close(vtpm_tx_fh);
++#ifndef VTPM_MUTLI_VM
++ close(vtpm_rx_fh);
++ free (guest_rx_file);
++#endif
++
++}
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/COPYING
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/COPYING Thu Sep 1 10:16:14 2005
@@ -0,0 +1,32 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/Makefile
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/Makefile Thu Sep 1 10:16:14 2005
@@ -0,0 +1,31 @@
+XEN_ROOT = ../..
+
+# Base definitions and rules
+include $(XEN_ROOT)/tools/vtpm_manager/Rules.mk
+
+SUBDIRS = crypto tcs util manager
+
+all: build
+
+build:
+ @set -e; for subdir in $(SUBDIRS); do \
+ $(MAKE) -C $$subdir $@; \
+ done
+
+install: build
+ @set -e; for subdir in $(SUBDIRS); do \
+ $(MAKE) -C $$subdir $@; \
+ done
+
+clean:
+ @set -e; for subdir in $(SUBDIRS); do \
+ $(MAKE) -C $$subdir $@; \
+ done
+
+
+mrproper:
+ @set -e; for subdir in $(SUBDIRS); do \
+ $(MAKE) -C $$subdir $@; \
+ done
+
+
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/README
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/README Thu Sep 1 10:16:14 2005
@@ -0,0 +1,89 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+
+Directory Structure
+===================
+tools/vtpm_manager/crypto -> crypto files
+tools/vtpm_manager/TCS -> TCS implementation
+tools/vtpm_manager/util -> Utility Library. Include disk-io and buffers.
+tools/vtpm_manager/manager -> VTPM Manager
+
+Compile Flags
+===================
+LOGGING_MODULES -> How extensive logging happens
+ see util/log.h for more info
+
+VTPM_MULTI_VM -> Defined: VTPMs run in their own VMs
+ Not Defined (default): VTPMs are processes
+
+# Debugging flags that may disappear without notice in the future
+
+DUMMY_BACKEND -> vtpm_manager listens on /tmp/in.fifo and
+ /tmp/out.fifo rather than backend
+
+MANUAL_DM_LAUNCH -> User must manually launch & kill VTPMs
+
+USE_FIXED_SRK_AUTH -> Do not randomly generate a random SRK & Owner
auth
+
+Requirements
+============
+- xen-unstable
+- IBM frontend/backend vtpm driver patch
+
+Single-VM Flow
+============================
+- Launch the VTPM manager (vtpm_managerd) which which begins listening to the
BE with one thread
+ and listens to a named fifo that is shared by the vtpms to commuincate with
the manager.
+- VTPM Manager listens to TPM BE.
+- When xend launches a tpm frontend equipped VM it contacts the manager over
the vtpm backend.
+- When the manager receives the open message from the BE, it launches a vtpm
+- Xend allows the VM to continue booting.
+- When a TPM request is issued to the front end, the front end transmits the
TPM request to the backend.
+- The manager receives the TPM requests and uses a named fifo to forward the
request to the vtpm.
+- The fifo listener begins listening for the reply from vtpm for the request.
+- Vtpm processes request and replies to manager over shared named fifo.
+- If needed, the vtpm may send a request to the vtpm_manager at any time to
save it's secrets to disk.
+- Manager receives response from vtpm and passes it back to backend for
forwarding to guest.
+
+NOTES:
+* SaveService SHOULD seal it's table before saving it to disk. However,
+ the current Xen infrastructure does not provide a mechanism for this to be
+ unsealed later. Specifically, the auth and wrapped key must be available ONLY
+ to the service, or it's not even worth encrypting
+
+ In the future the vtpm manager will be protected by an early boot mechanism
+ that will allow for better protection of it's data.
+
+TODO:
+- Timeout on crashed vtpms
+- create lock for shared fifo for talking to vtpms.
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/Rules.mk
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/Rules.mk Thu Sep 1 10:16:14 2005
@@ -0,0 +1,68 @@
+# Base definitions and rules (XEN_ROOT must be defined in including Makefile)
+include $(XEN_ROOT)/tools/Rules.mk
+
+#
+# Tool definitions
+#
+
+# Installation program and options
+INSTALL = install
+INSTALL_PROG = $(INSTALL) -m0755
+INSTALL_DIR = $(INSTALL) -d -m0755
+
+# Xen tools installation directory
+TOOLS_INSTALL_DIR = $(DESTDIR)/usr/bin
+
+# General compiler flags
+CFLAGS = -Wall -Werror -g3 -I.
+
+# For generating dependencies
+CFLAGS += -Wp,-MD,.$(@F).d
+
+DEP_FILES = .*.d
+
+# Generic project files
+HDRS = $(wildcard *.h)
+SRCS = $(wildcard *.c)
+OBJS = $(patsubst %.c,%.o,$(SRCS))
+
+# Generic (non-header) dependencies
+$(SRCS): Makefile $(XEN_ROOT)/tools/Rules.mk
$(XEN_ROOT)/tools/vtpm_manager/Rules.mk
+
+$(OBJS): $(SRCS)
+
+-include $(DEP_FILES)
+
+# Make sure these are just rules
+.PHONY : all build install clean
+
+#
+# Project-specific definitions
+#
+
+# Logging Level. See utils/tools.h for usage
+CFLAGS +=
-DLOGGING_MODULES="(BITMASK(VTPM_LOG_TCS)|BITMASK(VTPM_LOG_VTSP)|BITMASK(VTPM_LOG_VTPM)|BITMASK(VTPM_LOG_VTPM_DEEP))"
+
+# Silent Mode
+#CFLAGS += -DLOGGING_MODULES=0x0
+#CFLAGS += -DLOGGING_MODULES=0xff
+
+# Use frontend/backend pairs between manager & DMs?
+#CFLAGS += -DVTPM_MULTI_VM
+
+# vtpm_manager listens on /tmp/in.fifo and /tmp/out.fifo rather than backend
+#CFLAGS += -DDUMMY_BACKEND
+
+# Do not have manager launch DMs.
+#CFLAGS += -DMANUAL_DM_LAUNCH
+
+# Fixed SRK
+CFLAGS += -DUSE_FIXED_SRK_AUTH
+
+# TPM Hardware Device or TPM Simulator
+#CFLAGS += -DTPM_HWDEV
+
+# Include
+CFLAGS += -I$(XEN_ROOT)/tools/vtpm_manager/crypto
+CFLAGS += -I$(XEN_ROOT)/tools/vtpm_manager/util
+CFLAGS += -I$(XEN_ROOT)/tools/vtpm_manager/tcs
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/crypto/Makefile
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/crypto/Makefile Thu Sep 1 10:16:14 2005
@@ -0,0 +1,18 @@
+XEN_ROOT = ../../..
+include $(XEN_ROOT)/tools/vtpm_manager/Rules.mk
+
+BIN = libtcpaCrypto.a
+
+all: build
+
+build: $(BIN)
+
+install: build
+
+clean:
+ rm -f *.a *.so *.o *.rpm $(DEP_FILES)
+
+mrproper: clean
+
+$(BIN): $(OBJS)
+ $(AR) rcs $(BIN) $(OBJS)
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/crypto/crypto.c
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/crypto/crypto.c Thu Sep 1 10:16:14 2005
@@ -0,0 +1,88 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+//
+// crypto.c
+//
+// This file will handle all the TPM Crypto functionality
+//
+// ==================================================================
+
+#include <string.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#include "crypto.h"
+#include "log.h"
+
+/**
+ * Initialize cryptography library
+ * @rand: random seed
+ * @size: size of @rand
+ */
+void Crypto_Init(const BYTE* rand, int size) {
+ ERR_load_crypto_strings();
+ CRYPTO_malloc_init();
+ OpenSSL_add_all_algorithms();
+ SYM_CIPHER = EVP_aes_128_cbc();
+ RAND_poll();
+ if (rand == NULL)
+ return;
+
+ RAND_add(rand, size, size);
+}
+
+/**
+ * Shutdown cryptography library
+ */
+void Crypto_Exit() {
+ ERR_free_strings();
+ ERR_remove_state(0);
+ EVP_cleanup();
+}
+
+
+/**
+ * Get random data
+ * @data: (OUT) Random data
+ * @size: Size of @data
+ */
+void Crypto_GetRandom(void* data, int size) {
+ int result;
+
+ result = RAND_pseudo_bytes((BYTE*) data, size);
+
+ if (result <= 0)
+ vtpmlogerror (VTPM_LOG_CRYPTO, "RAND_pseudo_bytes failed: %s\n",
+ ERR_error_string (ERR_get_error(), NULL));
+}
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/crypto/crypto.h
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/crypto/crypto.h Thu Sep 1 10:16:14 2005
@@ -0,0 +1,175 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+//
+// crypto.h
+//
+// This file defines the TPM Crypto API
+//
+// ==================================================================
+
+#ifndef __CRYPTO_H__
+#define __CRYPTO_H__
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "tcg.h"
+#include "sym_crypto.h"
+
+#define CRYPTO_MAX_SIG_SIZE (2048 / 8)
+#define CRYPTO_MAX_RSA_KEY_SIZE (4096 / 8) //in bytes
+
+#define OAEP_P "TCPA"
+#define OAEP_P_SIZE 4
+
+// Algorithms supported by crypto. Stored in CRYPTO_INFO.algorithmID
+#define CRYPTO_ALGORITH_RSA 0x01
+
+// Supported Encryption Schemes CRYPTO_INFO.encScheme
+#define CRYPTO_ES_NONE 0x0001
+#define CRYPTO_ES_RSAESPKCSv15 0x0002
+#define CRYPTO_ES_RSAESOAEP_SHA1_MGF1 0x0003
+
+// Supported Signature schemes CRYPTO_INFO.sigScheme
+#define CRYPTO_SS_NONE 0x0001
+#define CRYPTO_SS_RSASSAPKCS1v15_SHA1 0x0002
+#define CRYPTO_SS_RSASSAPKCS1v15_DER 0x0003
+
+typedef struct CRYPTO_INFO {
+ void *keyInfo;
+ UINT32 algorithmID;
+ UINT32 encScheme;
+ UINT32 sigScheme;
+} CRYPTO_INFO;
+
+
+void Crypto_Init(const BYTE* rand, int size);
+
+void Crypto_Exit();
+
+void Crypto_GetRandom(void* data, int size);
+
+void Crypto_HMAC( const BYTE* text,
+ int text_len,
+ const BYTE* key,
+ int key_len,
+ BYTE* digest);
+
+TPM_RESULT Crypto_HMAC_buf (const buffer_t * text,
+ const buffer_t * key,
+ BYTE * o_digest); /* presumably of 20 bytes */
+
+void Crypto_SHA1Full( const BYTE* text,
+ UINT32 size,
+ BYTE* hash); //Complete 3part SHA1
+
+// o_hash needs to be large enough to hold the digest, ie 20 bytes
+TPM_RESULT Crypto_SHA1Full_buf (const buffer_t * buf,
+ BYTE * o_hash);
+
+void Crypto_SHA1Start(UINT32* maxNumBytes);
+void Crypto_SHA1Update(int numBytes, const BYTE* hashData);
+void Crypto_SHA1Complete( int hashDataSize,
+ const BYTE* hashData,
+ BYTE* hashValue);
+
+void Crypto_RSACreateKey( /*in*/ UINT32 keySize,
+ /*in*/ UINT32 pubExpSize,
+ /*in*/ BYTE *pubExp,
+ /*out*/ UINT32 *privExpSize,
+ /*out*/ BYTE *privExp,
+ /*out*/ UINT32 *modulusSize,
+ /*out*/ BYTE *modulus,
+ /*out*/ CRYPTO_INFO *keys);
+
+void Crypto_RSABuildCryptoInfo( /*[IN]*/ UINT32 pubExpSize,
+ /*[IN]*/ BYTE *pubExp,
+ /*[IN]*/ UINT32 privExpSize,
+ /*[IN]*/ BYTE *privExp,
+ /*[IN]*/ UINT32 modulusSize,
+ /*[IN]*/ BYTE *modulus,
+ /*[OUT]*/ CRYPTO_INFO* cryptoInfo);
+
+void Crypto_RSABuildCryptoInfoPublic( /*[IN]*/ UINT32 pubExpSize,
+ /*[IN]*/ BYTE *pubExp,
+ /*[IN]*/ UINT32 modulusSize,
+ /*[IN]*/ BYTE *modulus,
+ CRYPTO_INFO* cryptoInfo);
+
+//
+// symmetric pack and unpack operations
+//
+TPM_RESULT Crypto_RSAPackCryptoInfo (const CRYPTO_INFO* cryptoInfo,
+ BYTE ** io_buf, UINT32 * io_buflen);
+
+TPM_RESULT Crypto_RSAUnpackCryptoInfo (CRYPTO_INFO * ci,
+ BYTE * in, UINT32 len,
+ UINT32 * o_lenread);
+
+
+// return 0 on success, -1 on error
+int Crypto_RSAEnc( CRYPTO_INFO *keys,
+ UINT32 inDataSize,
+ BYTE *inData,
+ /*out*/ UINT32 *outDataSize,
+ /*out*/ BYTE *outData);
+
+// return 0 on success, -1 on error
+int Crypto_RSADec( CRYPTO_INFO *keys,
+ UINT32 inDataSize,
+ BYTE *inData,
+ /*out*/ UINT32 *outDataSize,
+ /*out*/ BYTE *outData);
+
+// return 0 on success, -1 on error
+int Crypto_RSASign( CRYPTO_INFO *keys,
+ UINT32 inDataSize,
+ BYTE *inData,
+ /*out*/ UINT32 *sigSize,
+ /*out*/ BYTE *sig);
+
+bool Crypto_RSAVerify( CRYPTO_INFO *keys,
+ UINT32 inDataSize,
+ BYTE *inData,
+ UINT32 sigSize,
+ BYTE *sig);
+
+//private:
+int RSA_verify_DER(int dtype, unsigned char *m, unsigned int m_len,
+ unsigned char *sigbuf, unsigned int siglen, CRYPTO_INFO
*key);
+
+int RSA_sign_DER(int type, unsigned char *m, unsigned int m_len,
+ unsigned char *sigret, unsigned int *siglen, CRYPTO_INFO *key);
+
+#endif // __CRYPTO_H__
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/crypto/hash.c
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/crypto/hash.c Thu Sep 1 10:16:14 2005
@@ -0,0 +1,153 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+//
+// hash.c
+//
+// This file will handle all the TPM Hash functionality
+//
+// ==================================================================
+
+#include <string.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#include <openssl/hmac.h>
+#include <openssl/sha.h>
+#include <openssl/bn.h>
+#include <openssl/rsa.h>
+
+#include "tcg.h" // for TPM_SUCCESS
+#include "crypto.h"
+
+static SHA_CTX g_shaContext;
+
+void Crypto_HMAC( const BYTE* text,
+ int text_len,
+ const BYTE* key,
+ int key_len,
+ BYTE* digest) {
+ if (text == NULL || key == NULL || text_len == 0 || key_len == 0)
+ return;
+
+ HMAC(EVP_sha1(), key, key_len, text, text_len, digest, NULL);
+}
+
+TPM_RESULT Crypto_HMAC_buf (const buffer_t * text,
+ const buffer_t * key,
+ BYTE * o_digest) { /* presumably of 20 bytes */
+
+ Crypto_HMAC (text->bytes, text->size,
+ key->bytes, key->size,
+ o_digest);
+
+ return TPM_SUCCESS;
+}
+
+
+/*
+ * SHA1
+ * (OUT) Create a SHA1 hash of text. Calls all three SHA1 steps internally
+ */
+void Crypto_SHA1Full( const BYTE* text,
+ uint32_t size,
+ BYTE* hash) {
+
+ if (text == NULL || size == 0)
+ return;
+
+ // Run SHA1Start + SHAUpdate (if necessary) + SHAComplete
+ uint32_t maxBytes; // Not used for anything
+ Crypto_SHA1Start(&maxBytes);
+
+ while (size > 64){
+ Crypto_SHA1Update(64, text);
+ size -= 64;
+ text += 64;
+ }
+
+ Crypto_SHA1Complete(size, text, hash);
+}
+
+// same thing using buffer_t
+TPM_RESULT Crypto_SHA1Full_buf (const buffer_t * buf,
+ BYTE * o_digest) {
+
+ if (buf->bytes == NULL || buf->size == 0)
+ return TPM_BAD_PARAMETER;
+
+ Crypto_SHA1Full (buf->bytes, buf->size, o_digest);
+
+ return TPM_SUCCESS;
+}
+
+
+/*
+ * Initialize SHA1
+ * (OUT) Maximum number of bytes that can be sent to SHA1Update.
+ * Must be a multiple of 64 bytes.
+ */
+void Crypto_SHA1Start(uint32_t* maxNumBytes) {
+ int max = SHA_CBLOCK;
+ // Initialize the crypto library
+ SHA1_Init(&g_shaContext);
+ *maxNumBytes = max;
+}
+
+/*
+ * Process SHA1
+ * @numBytes: (IN) The number of bytes in hashData.
+ * Must be a multiple of 64 bytes.
+ * @hashData: (IN) Bytes to be hashed.
+ */
+void Crypto_SHA1Update(int numBytes, const BYTE* hashData) {
+
+ if (hashData == NULL || numBytes == 0 || numBytes%64 != 0)
+ return;
+
+ SHA1_Update(&g_shaContext, hashData, numBytes);
+}
+
+/*
+ * Complete the SHA1 process
+ * @hashDataSize: (IN) Number of bytes in hashData.
+ * Must be a multiple of 64 bytes.
+ * @hashData: (IN) Final bytes to be hashed.
+ * @hashValue: (OUT) The output of the SHA-1 hash.
+ */
+void Crypto_SHA1Complete(int hashDataSize,
+ const BYTE* hashData,
+ BYTE* hashValue) {
+ SHA1_Update(&g_shaContext, hashData, hashDataSize);
+ SHA1_Final(hashValue, &g_shaContext);
+}
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/crypto/rsa.c
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/crypto/rsa.c Thu Sep 1 10:16:14 2005
@@ -0,0 +1,434 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+//
+// rsa.c
+//
+// This file will handle all the TPM RSA crypto functionality
+//
+// ==================================================================
+
+#include <string.h>
+#include <openssl/crypto.h>
+#include <openssl/evp.h>
+#include <openssl/bn.h>
+#include <openssl/rsa.h>
+#include <openssl/rand.h>
+#include <openssl/x509.h>
+
+#include <openssl/err.h>
+#include <stdio.h>
+
+#include "tcg.h"
+#include "buffer.h"
+#include "crypto.h"
+#include "log.h"
+
+void Crypto_RSACreateKey( /*in*/ UINT32 keySize,
+ /*in*/ UINT32 pubExpSize,
+ /*in*/ BYTE *pubExp,
+ /*out*/ UINT32 *privExpSize,
+ /*out*/ BYTE *privExp,
+ /*out*/ UINT32 *modulusSize,
+ /*out*/ BYTE *modulus,
+ /*out*/ CRYPTO_INFO *keys) {
+ unsigned long e_value;
+
+ if (pubExpSize == 0) // Default e = 2^16+1
+ e_value = (0x01 << 16) + 1;
+ else {
+ // This is not supported, but the following line MIGHT work
+ // under then assumption that the format is BigNum compatable
+ // Though it's not in the spec, so who knows what it is.
+ // Forcing the default.
+ //BN_bin2bn(pubExp, pubExpSize, NULL);
+ e_value = (0x01 << 16) + 1;
+ }
+
+ RSA *rsa = RSA_generate_key(keySize, e_value, NULL, NULL);
+
+ if (keys) {
+ keys->keyInfo = rsa;
+ keys->algorithmID = CRYPTO_ALGORITH_RSA;
+ }
+
+ if (modulus) *modulusSize = BN_bn2bin(rsa->n, modulus);
+ if (privExp) *privExpSize = BN_bn2bin(rsa->d, privExp);
+}
+
+// Create a CRYPTO_INFO struct from the BYTE * key parts.
+// If pubExp info is NULL, use TCG default.
+// If there is a remainder while calculating the privExp, return FALSE.
+
+void Crypto_RSABuildCryptoInfo( /*[IN]*/ UINT32 pubExpSize,
+ /*[IN]*/ BYTE *pubExp,
+ /*[IN]*/ UINT32 privExpSize,
+ /*[IN]*/ BYTE *privExp,
+ /*[IN]*/ UINT32 modulusSize,
+ /*[IN]*/ BYTE *modulus,
+ CRYPTO_INFO* cryptoInfo) {
+ cryptoInfo->keyInfo = RSA_new();
+ RSA *rsa = (RSA *) cryptoInfo->keyInfo;
+
+ rsa->e = BN_new();
+
+ if (pubExpSize == 0) { // Default e = 2^16+1
+ BN_set_bit(rsa->e, 16);
+ BN_set_bit(rsa->e, 0);
+ } else {
+ // This is not supported, but the following line MIGHT work
+ // under then assumption that the format is BigNum compatable
+ // Though it's not in the spec, so who knows what it is.
+ // Forcing the default.
+ //BN_bin2bn(pubExp, pubExpSize, NULL);
+ BN_set_bit(rsa->e, 16);
+ BN_set_bit(rsa->e, 0);
+ }
+
+ rsa->n = BN_bin2bn(modulus, modulusSize, NULL);
+ rsa->d = BN_bin2bn(privExp, privExpSize, NULL);
+}
+
+// Create a CRYPTO_INFO struct from the BYTE * key parts.
+// If pubExp info is NULL, use TCG default.
+// If there is a remainder while calculating the privExp, return FALSE.
+
+void Crypto_RSABuildCryptoInfoPublic( /*[IN]*/ UINT32 pubExpSize,
+ /*[IN]*/ BYTE *pubExp,
+ /*[IN]*/ UINT32 modulusSize,
+ /*[IN]*/ BYTE *modulus,
+ CRYPTO_INFO* cryptoInfo) {
+ cryptoInfo->keyInfo = RSA_new();
+ RSA *rsa = (RSA *) cryptoInfo->keyInfo;
+
+ rsa->e = BN_new();
+
+ if (pubExpSize == 0) { // Default e = 2^16+1
+ BN_set_bit(rsa->e, 16);
+ BN_set_bit(rsa->e, 0);
+ } else {
+ // This is not supported, but the following line MIGHT work
+ // under then assumption that the format is BigNum compatable
+ // Though it's not in the spec, so who knows what it is.
+ // Forcing the default.
+ //BN_bin2bn(pubExp, pubExpSize, NULL);
+ BN_set_bit(rsa->e, 16);
+ BN_set_bit(rsa->e, 0);
+ }
+
+ rsa->n = BN_bin2bn(modulus, modulusSize, NULL);
+
+}
+
+int Crypto_RSAEnc( CRYPTO_INFO *key,
+ UINT32 inDataSize,
+ BYTE *inData,
+ /*out*/ UINT32 *outDataSize,
+ /*out*/ BYTE *outData) {
+ RSA *rsa = (RSA *) key->keyInfo;
+ UINT32 paddedDataSize = RSA_size (rsa);
+ BYTE *paddedData = (BYTE *)malloc(sizeof(BYTE) * paddedDataSize);
+ int rc;
+
+ if (paddedData == NULL)
+ return -1;
+
+ *outDataSize = 0;
+
+ switch (key->encScheme) {
+ case CRYPTO_ES_RSAESPKCSv15:
+ if (RSA_padding_add_PKCS1_type_2(paddedData, paddedDataSize, inData,
inDataSize) <= 0) {
+ rc = -1;
+ goto abort_egress;
+ }
+ break;
+ case CRYPTO_ES_RSAESOAEP_SHA1_MGF1:
+ if
(RSA_padding_add_PKCS1_OAEP(paddedData,paddedDataSize,inData,inDataSize, (BYTE
*) OAEP_P,OAEP_P_SIZE) <= 0 ) {
+ rc = -1;
+ goto abort_egress;
+ }
+ break;
+ default:
+ rc = -1;
+ goto abort_egress;
+ }
+
+ rc = RSA_public_encrypt(paddedDataSize, paddedData, outData, rsa,
RSA_NO_PADDING);
+ if (rc == -1)
+ goto abort_egress;
+
+ *outDataSize = rc;
+
+ if (rc > 0) rc = 0;
+
+ goto egress;
+
+ abort_egress:
+ egress:
+
+ if (paddedData)
+ free (paddedData);
+ return rc;
+
+}
+
+int Crypto_RSADec( CRYPTO_INFO *key,
+ UINT32 inDataSize,
+ BYTE *inData,
+ /*out*/ UINT32 *outDataSize,
+ /*out*/ BYTE *outData) {
+
+ RSA *rsa = (RSA *) key->keyInfo;
+ UINT32 paddedDataSize = RSA_size (rsa);
+ BYTE *paddedData = (BYTE *)malloc(sizeof(BYTE) * paddedDataSize);
+ int rc;
+
+ if (paddedData == NULL)
+ goto abort_egress;
+
+ rc = RSA_private_decrypt(inDataSize, inData, paddedData, rsa,
RSA_NO_PADDING);
+ if (rc == -1) {
+ vtpmlogerror(VTPM_LOG_CRYPTO, "RSA_private_decrypt: %s\n",
ERR_error_string(ERR_get_error(), NULL));
+ goto abort_egress;
+ }
+
+ paddedDataSize = rc;
+
+ switch (key->encScheme) {
+ case CRYPTO_ES_RSAESPKCSv15:
+ rc = RSA_padding_check_PKCS1_type_2 (outData, paddedDataSize,
+ paddedData + 1, paddedDataSize - 1,
+ RSA_size(rsa));
+ if (rc == -1) {
+ vtpmlogerror(VTPM_LOG_CRYPTO, "RSA_padding_check_PKCS1_type_2: %s\n",
+ ERR_error_string(ERR_get_error(), NULL));
+ goto abort_egress;
+ }
+ *outDataSize = rc;
+ break;
+ case CRYPTO_ES_RSAESOAEP_SHA1_MGF1:
+ rc = RSA_padding_check_PKCS1_OAEP(outData, paddedDataSize,
+ paddedData + 1, paddedDataSize - 1,
+ RSA_size(rsa),
+ (BYTE *) OAEP_P, OAEP_P_SIZE);
+ if (rc == -1) {
+ vtpmlogerror(VTPM_LOG_CRYPTO, "RSA_padding_check_PKCS1_OAEP: %s\n",
+ ERR_error_string(ERR_get_error(), NULL));
+ goto abort_egress;
+ }
+ *outDataSize = rc;
+ break;
+ default:
+ *outDataSize = 0;
+ }
+
+ free(paddedData); paddedData = NULL;
+ goto egress;
+
+ abort_egress:
+
+ if (paddedData)
+ free (paddedData);
+ return -1;
+
+ egress:
+ return 0;
+}
+
+// Signs either a SHA1 digest of a message or a DER encoding of a message
+// Textual messages MUST be encoded or Hashed before sending into this function
+// It will NOT SHA the message.
+int Crypto_RSASign( CRYPTO_INFO *key,
+ UINT32 inDataSize,
+ BYTE *inData,
+ /*out*/ UINT32 *sigSize,
+ /*out*/ BYTE *sig) {
+ int status;
+ unsigned int intSigSize;
+
+ switch(key->sigScheme) {
+ case CRYPTO_SS_RSASSAPKCS1v15_SHA1:
+ status = RSA_sign(NID_sha1, inData, inDataSize, sig, &intSigSize, (RSA *)
key->keyInfo);
+ break;
+ case CRYPTO_SS_RSASSAPKCS1v15_DER:
+ // status = Crypto_RSA_sign_DER(NID_md5_sha1, inData, inDataSize,
sig, &intSigSize, key);
+ vtpmlogerror(VTPM_LOG_CRYPTO, "Crypto: Unimplemented sign type (%d)\n",
key->sigScheme);
+ status = 0;
+ break;
+ default:
+ status = 0;
+ }
+
+ if (status == 0) {
+ *sigSize = 0;
+ vtpmlogerror(VTPM_LOG_CRYPTO, "%s\n", ERR_error_string(ERR_get_error(),
NULL));
+ return -1;
+ }
+
+ *sigSize = (UINT32) intSigSize;
+ return 0;
+}
+
+bool Crypto_RSAVerify( CRYPTO_INFO *key,
+ UINT32 inDataSize,
+ BYTE *inData,
+ UINT32 sigSize,
+ BYTE *sig) {
+ int status;
+
+ switch(key->sigScheme){
+ case CRYPTO_SS_RSASSAPKCS1v15_SHA1:
+ status = RSA_verify(NID_sha1, inData, inDataSize, sig, sigSize, (RSA *)
key->keyInfo);
+ break;
+ case CRYPTO_SS_RSASSAPKCS1v15_DER:
+ //status = Crypto_RSA_verify_DER(NID_md5_sha1, inData, inDataSize, sig,
sigSize, key);
+ vtpmlogerror(VTPM_LOG_CRYPTO, "Crypto: Unimplemented sign type (%d)\n",
key->sigScheme);
+ status = 0;
+ break;
+ default:
+ status = 0;
+ }
+
+ if (status)
+ return(1);
+ else {
+ vtpmlogerror(VTPM_LOG_CRYPTO, "RSA verify: %s\n",
ERR_error_string(ERR_get_error(), NULL));
+ return(0);
+ }
+
+}
+
+// helper which packs everything into a BIO!
+
+// packs the parameters first, then the private key, then the public key
+// if *io_buf is NULL, allocate it here as needed. otherwise its size is in
+// *io_buflen
+TPM_RESULT Crypto_RSAPackCryptoInfo (const CRYPTO_INFO* cryptoInfo,
+ BYTE ** io_buf, UINT32 * io_buflen) {
+ TPM_RESULT status = TPM_SUCCESS;
+ BYTE * buf;
+ long len, outlen = *io_buflen;
+
+ const long PARAMSLEN = 3*sizeof(UINT32);
+
+ RSA *rsa = (RSA *) cryptoInfo->keyInfo;
+
+ BIO *mem = BIO_new(BIO_s_mem());
+
+
+ // write the openssl keys to the BIO
+ if ( i2d_RSAPrivateKey_bio (mem, rsa) == 0 ) {
+ ERR_print_errors_fp (stderr);
+ ERRORDIE (TPM_SIZE);
+ }
+ if ( i2d_RSAPublicKey_bio (mem, rsa) == 0 ) {
+ ERR_print_errors_fp (stderr);
+ ERRORDIE (TPM_SIZE);
+ }
+
+ // get the buffer out
+ len = BIO_get_mem_data (mem, &buf);
+
+ // see if we need to allocate a return buffer
+ if (*io_buf == NULL) {
+ *io_buf = (BYTE*) malloc (PARAMSLEN + len);
+ if (*io_buf == NULL)
+ ERRORDIE (TPM_SIZE);
+ } else { // *io_buf is already allocated
+ if (outlen < len + PARAMSLEN)
+ ERRORDIE (TPM_SIZE); // but not large enough!
+ }
+
+ // copy over the parameters (three UINT32's starting at algorithmID)
+ memcpy (*io_buf, &cryptoInfo->algorithmID, PARAMSLEN);
+
+ // copy over the DER keys
+ memcpy (*io_buf + PARAMSLEN, buf, len);
+
+ *io_buflen = len + PARAMSLEN;
+
+ goto egress;
+
+
+ abort_egress:
+ egress:
+
+ BIO_free (mem);
+
+ return status;
+}
+
+
+
+// sets up ci, and returns the number of bytes read in o_lenread
+TPM_RESULT Crypto_RSAUnpackCryptoInfo (CRYPTO_INFO * ci,
+ BYTE * in, UINT32 len,
+ UINT32 * o_lenread) {
+
+ TPM_RESULT status = TPM_SUCCESS;
+ long l;
+ BIO *mem;
+ RSA *rsa;
+
+ // first load up the params
+ l = 3 * sizeof(UINT32);
+ memcpy (&ci->algorithmID, in, l);
+ len -= l;
+ in += l;
+
+ // and now the openssl keys, private first
+ mem = BIO_new_mem_buf (in, len);
+
+ if ( (rsa = d2i_RSAPrivateKey_bio (mem, NULL)) == NULL ) {
+ ERR_print_errors_fp (stderr);
+ ERRORDIE (TPM_BAD_PARAMETER);
+ }
+ // now use the same RSA object and fill in the private key
+ if ( d2i_RSAPublicKey_bio (mem, &rsa) == NULL ) {
+ ERR_print_errors_fp (stderr);
+ ERRORDIE (TPM_BAD_PARAMETER);
+ }
+
+ ci->keyInfo = rsa; // needs to be freed somehow later
+
+ // FIXME: havent figured out yet how to tell how many bytes were read in the
+ // above oprations! so o_lenread is not set
+
+ goto egress;
+
+ abort_egress:
+ egress:
+
+ BIO_free (mem);
+
+ return status;
+}
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/crypto/sym_crypto.c
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/crypto/sym_crypto.c Thu Sep 1 10:16:14 2005
@@ -0,0 +1,242 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+//
+// sym_crypto.c
+//
+// Symmetric crypto portion of crypto
+//
+// ==================================================================
+
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+
+#include "tcg.h"
+#include "sym_crypto.h"
+
+typedef enum crypt_op_type_t {
+ CRYPT_ENCRYPT,
+ CRYPT_DECRYPT
+} crypt_op_type_t;
+
+TPM_RESULT ossl_symcrypto_op (symkey_t* key,
+ const buffer_t* in,
+ const buffer_t* iv,
+ buffer_t * out,
+ crypt_op_type_t optype);
+
+
+// this is initialized in Crypto_Init()
+const EVP_CIPHER * SYM_CIPHER = NULL;
+
+const BYTE ZERO_IV[EVP_MAX_IV_LENGTH] = {0};
+
+
+TPM_RESULT Crypto_symcrypto_initkey (symkey_t * key, const buffer_t* keybits) {
+ TPM_RESULT status = TPM_SUCCESS;
+
+ EVP_CIPHER_CTX_init (&key->context);
+
+ key->cipher = SYM_CIPHER;
+
+ status = buffer_init_copy (&key->key, keybits);
+ STATUSCHECK(status);
+
+ goto egress;
+
+ abort_egress:
+ EVP_CIPHER_CTX_cleanup (&key->context);
+
+ egress:
+
+ return status;
+}
+
+
+
+TPM_RESULT Crypto_symcrypto_genkey (symkey_t * key) {
+ int res;
+ TPM_RESULT status = TPM_SUCCESS;
+
+ // hmm, EVP_CIPHER_CTX_init does not return a value
+ EVP_CIPHER_CTX_init (&key->context);
+
+ key->cipher = SYM_CIPHER;
+
+ status = buffer_init (&key->key, EVP_CIPHER_key_length(key->cipher), NULL);
+ STATUSCHECK (status);
+
+ // and generate the key material
+ res = RAND_pseudo_bytes (key->key.bytes, key->key.size);
+ if (res < 0)
+ ERRORDIE (TPM_SHORTRANDOM);
+
+
+ goto egress;
+
+ abort_egress:
+ EVP_CIPHER_CTX_cleanup (&key->context);
+ buffer_free (&key->key);
+
+ egress:
+ return status;
+}
+
+
+TPM_RESULT Crypto_symcrypto_encrypt (symkey_t* key,
+ const buffer_t* clear,
+ buffer_t* o_cipher) {
+ TPM_RESULT status = TPM_SUCCESS;
+
+ buffer_t iv, cipher_alias;
+
+ buffer_init_const (&iv, EVP_MAX_IV_LENGTH, ZERO_IV);
+
+ buffer_init (o_cipher,
+ clear->size +
+ EVP_CIPHER_iv_length(key->cipher) +
+ EVP_CIPHER_block_size (key->cipher),
+ 0);
+
+ // copy the IV into the front
+ buffer_copy (o_cipher, &iv);
+
+ // make an alias into which we'll put the ciphertext
+ buffer_init_alias (&cipher_alias, o_cipher,
EVP_CIPHER_iv_length(key->cipher), 0);
+
+ status = ossl_symcrypto_op (key, clear, &iv, &cipher_alias, CRYPT_ENCRYPT);
+ STATUSCHECK (status);
+
+ // set the output size correctly
+ o_cipher->size += cipher_alias.size;
+
+ goto egress;
+
+ abort_egress:
+
+ egress:
+
+ return status;
+
+}
+
+
+
+TPM_RESULT Crypto_symcrypto_decrypt (symkey_t* key,
+ const buffer_t* cipher,
+ buffer_t* o_clear) {
+ TPM_RESULT status = TPM_SUCCESS;
+
+ buffer_t iv, cipher_alias;
+
+ // alias for the IV
+ buffer_init_alias (&iv, cipher, 0, EVP_CIPHER_iv_length(key->cipher));
+
+ // make an alias to where the ciphertext is, after the IV
+ buffer_init_alias (&cipher_alias, cipher, EVP_CIPHER_iv_length(key->cipher),
0);
+
+ // prepare the output buffer
+ status = buffer_init (o_clear,
+ cipher->size
+ - EVP_CIPHER_iv_length(key->cipher)
+ + EVP_CIPHER_block_size(key->cipher),
+ 0);
+ STATUSCHECK(status);
+
+ // and decrypt
+ status = ossl_symcrypto_op (key, &cipher_alias, &iv, o_clear, CRYPT_DECRYPT);
+ STATUSCHECK (status);
+
+ goto egress;
+
+ abort_egress:
+ buffer_free (o_clear);
+
+ egress:
+
+ return status;
+}
+
+
+
+TPM_RESULT Crypto_symcrypto_freekey (symkey_t * key) {
+ buffer_memset (&key->key, 0);
+ buffer_free (&key->key);
+
+ EVP_CIPHER_CTX_cleanup (&key->context);
+
+ return TPM_SUCCESS;
+}
+
+
+TPM_RESULT ossl_symcrypto_op (symkey_t* key,
+ const buffer_t* in,
+ const buffer_t* iv,
+ buffer_t * out,
+ crypt_op_type_t optype) {
+ TPM_RESULT status = TPM_SUCCESS;
+
+ int inlen, outlen;
+ tpm_size_t running;
+
+ if ( ! EVP_CipherInit_ex (&key->context,
+ key->cipher, NULL, key->key.bytes, iv->bytes,
+ optype == CRYPT_ENCRYPT ? 1 : 0) )
+ ERRORDIE (TPM_FAIL);
+
+
+
+ inlen = in->size;
+
+ outlen = 0;
+ running = 0;
+
+
+ if ( ! EVP_CipherUpdate (&key->context, out->bytes, &outlen, in->bytes,
inlen) )
+ ERRORDIE (TPM_FAIL);
+
+ running += outlen;
+
+ if ( ! EVP_CipherFinal_ex (&key->context, out->bytes + running, &outlen) )
+ ERRORDIE (TPM_FAIL);
+
+ running += outlen;
+
+ out->size = running;
+
+ goto egress;
+
+ abort_egress:
+ egress:
+
+ return status;
+}
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/crypto/sym_crypto.h
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/crypto/sym_crypto.h Thu Sep 1 10:16:14 2005
@@ -0,0 +1,72 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+//
+// sym_crypto.h
+//
+// Symmetric Crypto
+//
+// ==================================================================
+
+#ifndef _SYM_CRYPTO_H
+#define _SYM_CRYPTO_H
+
+#include <openssl/evp.h>
+#include "buffer.h"
+
+typedef struct symkey_t {
+ buffer_t key;
+
+ EVP_CIPHER_CTX context;
+ const EVP_CIPHER * cipher;
+} symkey_t;
+
+extern const EVP_CIPHER * SYM_CIPHER;
+
+TPM_RESULT Crypto_symcrypto_genkey (symkey_t * key);
+
+TPM_RESULT Crypto_symcrypto_initkey (symkey_t * key, const buffer_t* keybits);
+
+
+// these functions will allocate their output buffers
+TPM_RESULT Crypto_symcrypto_encrypt (symkey_t* key,
+ const buffer_t* clear,
+ buffer_t* o_cipher);
+
+TPM_RESULT Crypto_symcrypto_decrypt (symkey_t* key,
+ const buffer_t* cipher,
+ buffer_t* o_clear);
+
+// only free the internal parts, not the 'key' ptr
+TPM_RESULT Crypto_symcrypto_freekey (symkey_t * key);
+
+#endif /* _SYM_CRYPTO_H */
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/manager/Makefile
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/manager/Makefile Thu Sep 1 10:16:14 2005
@@ -0,0 +1,27 @@
+XEN_ROOT = ../../..
+include $(XEN_ROOT)/tools/vtpm_manager/Rules.mk
+
+BIN = vtpm_managerd
+
+all: build
+
+build: $(BIN)
+
+install: build
+ if [ ! -d "$(DESTDIR)/var/vtpm/fifos" ]; \
+ then mkdir -p $(DESTDIR)/var/vtpm/fifos; \
+ fi
+ $(INSTALL_PROG) $(BIN) $(TOOLS_INSTALL_DIR)
+
+clean:
+ rm -f *.a *.so *.o *.rpm $(DEP_FILES)
+
+mrproper: clean
+ rm -f $(BIN)
+
+$(BIN): $(OBJS)
+ $(CC) $(LDFLAGS) $^ $(LIBS) -o $@
+
+# libraries
+LIBS += ../tcs/libTCS.a ../util/libTCGUtils.a ../crypto/libtcpaCrypto.a
+LIBS += -lcrypto -lpthread -lrt -lm
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/manager/dmictl.c
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/manager/dmictl.c Thu Sep 1 10:16:14 2005
@@ -0,0 +1,339 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+//
+// dmictl.c
+//
+// Functions for creating and destroying DMIs
+//
+// ==================================================================
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+
+#ifndef VTPM_MUTLI_VM
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <fcntl.h>
+ #include <signal.h>
+ #include <wait.h>
+#endif
+
+#include "vtpmpriv.h"
+#include "bsg.h"
+#include "buffer.h"
+#include "log.h"
+#include "hashtable.h"
+#include "hashtable_itr.h"
+
+#define TPM_EMULATOR_PATH "/usr/bin/vtpmd"
+
+TPM_RESULT close_dmi( VTPM_DMI_RESOURCE *dmi_res) {
+ TPM_RESULT status = TPM_FAIL;
+
+ if (dmi_res == NULL)
+ return TPM_SUCCESS;
+
+ status = TCS_CloseContext(dmi_res->TCSContext);
+ free ( dmi_res->NVMLocation );
+ dmi_res->connected = FALSE;
+
+#ifndef VTPM_MULTI_VM
+ free(dmi_res->guest_tx_fname);
+ free(dmi_res->vtpm_tx_fname);
+
+ close(dmi_res->guest_tx_fh); dmi_res->guest_tx_fh = -1;
+ close(dmi_res->vtpm_tx_fh); dmi_res->vtpm_tx_fh = -1;
+
+
+ #ifndef MANUAL_DM_LAUNCH
+ if (dmi_res->dmi_id != VTPM_CTL_DM) {
+ if (dmi_res->dmi_pid != 0) {
+ vtpmloginfo(VTPM_LOG_VTPM, "Killing dmi on pid %d.\n", dmi_res->dmi_pid);
+ if ((kill(dmi_res->dmi_pid, SIGKILL) !=0) ||
+ (waitpid(dmi_res->dmi_pid, NULL, 0) != dmi_res->dmi_pid)){
+ vtpmlogerror(VTPM_LOG_VTPM, "Could not kill dmi on pid %d.\n",
dmi_res->dmi_pid);
+ status = TPM_FAIL;
+ }
+ } else
+ vtpmlogerror(VTPM_LOG_VTPM, "Could not kill dmi because it's pid was
0.\n");
+ }
+ #endif
+#endif
+
+ return status;
+}
+
+TPM_RESULT VTPM_Handle_New_DMI( const buffer_t *param_buf) {
+
+ VTPM_DMI_RESOURCE *new_dmi=NULL;
+ TPM_RESULT status=TPM_FAIL;
+ BYTE type;
+ UINT32 dmi_id, domain_id, *dmi_id_key;
+ int fh;
+
+#ifndef VTPM_MUTLI_VM
+ char dmi_id_str[11]; // UINT32s are up to 10 digits + NULL
+ struct stat file_info;
+#endif
+
+ if (param_buf == NULL) { // Assume creation of Dom 0 control
+ type = 0;
+ domain_id = VTPM_CTL_DM;
+ dmi_id = VTPM_CTL_DM;
+ } else if (buffer_len(param_buf) != sizeof(BYTE) + sizeof(UINT32) *2) {
+ vtpmloginfo(VTPM_LOG_VTPM, "New DMI command wrong length: %d.\n",
buffer_len(param_buf));
+ status = TPM_BAD_PARAMETER;
+ goto abort_egress;
+ } else {
+ BSG_UnpackList( param_buf->bytes, 3,
+ BSG_TYPE_BYTE, &type,
+ BSG_TYPE_UINT32, &domain_id,
+ BSG_TYPE_UINT32, &dmi_id);
+ }
+
+ new_dmi = (VTPM_DMI_RESOURCE *) hashtable_search(vtpm_globals->dmi_map,
&dmi_id);
+ if (new_dmi == NULL) {
+ vtpmloginfo(VTPM_LOG_VTPM, "Creating new DMI instance %d attached on
domain %d.\n", dmi_id, domain_id);
+ // Brand New DMI. Initialize the persistent pieces
+ if ((new_dmi = (VTPM_DMI_RESOURCE *) malloc (sizeof(VTPM_DMI_RESOURCE)))
== NULL) {
+ status = TPM_RESOURCES;
+ goto abort_egress;
+ }
+ memset(new_dmi, 0, sizeof(VTPM_DMI_RESOURCE));
+ new_dmi->dmi_id = dmi_id;
+ new_dmi->connected = FALSE;
+
+ if ((dmi_id_key = (UINT32 *) malloc (sizeof(UINT32))) == NULL) {
+ status = TPM_RESOURCES;
+ goto abort_egress;
+ }
+ *dmi_id_key = new_dmi->dmi_id;
+
+ // install into map
+ if (!hashtable_insert(vtpm_globals->dmi_map, dmi_id_key, new_dmi)){
+ free(new_dmi);
+ free(dmi_id_key);
+ status = TPM_FAIL;
+ goto egress;
+ }
+
+ } else
+ vtpmloginfo(VTPM_LOG_VTPM, "Re-attaching DMI instance %d on domain %d
.\n", dmi_id, domain_id);
+
+ if (new_dmi->connected) {
+ vtpmlogerror(VTPM_LOG_VTPM, "Attempt to re-attach, currently attached
instance %d. Ignoring\n", dmi_id);
+ status = TPM_BAD_PARAMETER;
+ goto egress;
+ }
+
+ // Initialize the Non-persistent pieces
+ new_dmi->dmi_domain_id = domain_id;
+ new_dmi->NVMLocation = NULL;
+
+ new_dmi->TCSContext = 0;
+ TPMTRYRETURN( TCS_OpenContext(&new_dmi->TCSContext) );
+
+ new_dmi->NVMLocation = (char *) malloc(11 + strlen(DMI_NVM_FILE));
+ sprintf(new_dmi->NVMLocation, DMI_NVM_FILE, (uint32_t) new_dmi->dmi_id);
+
+ // Measure DMI
+ // FIXME: This will measure DMI. Until then use a fixed DMI_Measurement value
+ /*
+ fh = open(TPM_EMULATOR_PATH, O_RDONLY);
+ stat_ret = fstat(fh, &file_stat);
+ if (stat_ret == 0)
+ dmi_size = file_stat.st_size;
+ else {
+ vtpmlogerror(VTPM_LOG_VTPM, "Could not open tpm_emulator!!\n");
+ status = TPM_IOERROR;
+ goto abort_egress;
+ }
+ dmi_buffer
+ */
+ memset(&new_dmi->DMI_measurement, 0xcc, sizeof(TPM_DIGEST));
+
+#ifndef VTPM_MULTI_VM
+ if (dmi_id != VTPM_CTL_DM) {
+ // Create a pair of fifo pipes
+ if( (new_dmi->guest_tx_fname = (char *) malloc(11 +
strlen(GUEST_TX_FIFO))) == NULL){
+ status = TPM_RESOURCES;
+ goto abort_egress;
+ }
+ sprintf(new_dmi->guest_tx_fname, GUEST_TX_FIFO, (uint32_t)
dmi_id);
+
+ if ((new_dmi->vtpm_tx_fname = (char *) malloc(11 +
strlen(VTPM_TX_FIFO))) == NULL) {
+ status = TPM_RESOURCES;
+ goto abort_egress;
+ }
+ sprintf(new_dmi->vtpm_tx_fname, VTPM_TX_FIFO, (uint32_t)
dmi_id);
+
+ new_dmi->guest_tx_fh = -1;
+ new_dmi->vtpm_tx_fh= -1;
+
+ if ( stat(new_dmi->guest_tx_fname, &file_info) == -1) {
+ if ( mkfifo(new_dmi->guest_tx_fname, S_IWUSR | S_IRUSR ) ){
+ status = TPM_FAIL;
+ goto abort_egress;
+ }
+ }
+
+ if ( (fh = open(new_dmi->vtpm_tx_fname, O_RDWR)) == -1) {
+ if ( mkfifo(new_dmi->vtpm_tx_fname, S_IWUSR | S_IRUSR ) ) {
+ status = TPM_FAIL;
+ goto abort_egress;
+ }
+ }
+
+ // Launch DMI
+ sprintf(dmi_id_str, "%d", (int) dmi_id);
+#ifdef MANUAL_DM_LAUNCH
+ vtpmlogerror(VTPM_LOG_VTPM, "FAKING starting vtpm with dmi=%s\n",
dmi_id_str);
+ new_dmi->dmi_pid = 0;
+#else
+ pid_t pid = fork();
+
+ if (pid == -1) {
+ vtpmlogerror(VTPM_LOG_VTPM, "Could not fork to launch
vtpm\n");
+ status = TPM_RESOURCES;
+ goto abort_egress;
+ } else if (pid == 0) {
+ if ( stat(new_dmi->NVMLocation, &file_info) == -1)
+ execl (TPM_EMULATOR_PATH, "vtmpd", "clear",
dmi_id_str, NULL);
+ else
+ execl (TPM_EMULATOR_PATH, "vtpmd", "save",
dmi_id_str, NULL);
+
+ // Returning from these at all is an error.
+ vtpmlogerror(VTPM_LOG_VTPM, "Could not exec to launch
vtpm\n");
+ } else {
+ new_dmi->dmi_pid = pid;
+ vtpmloginfo(VTPM_LOG_VTPM, "Launching DMI on PID = %d\n", pid);
+ }
+#endif // MANUAL_DM_LAUNCH
+ }
+#else // VTPM_MUTLI_VM
+ // FIXME: Measure DMI through call to Measurement agent in platform.
+#endif
+
+ vtpm_globals->DMI_table_dirty = TRUE;
+ new_dmi->connected = TRUE;
+ status=TPM_SUCCESS;
+ goto egress;
+
+ abort_egress:
+ close_dmi( new_dmi );
+
+ egress:
+ return status;
+}
+
+TPM_RESULT VTPM_Handle_Close_DMI( const buffer_t *param_buf) {
+
+ TPM_RESULT status=TPM_FAIL;
+ VTPM_DMI_RESOURCE *dmi_res=NULL;
+ UINT32 dmi_id;
+
+ if ((param_buf == NULL) || (buffer_len(param_buf) != sizeof(UINT32)) ) {
+ vtpmlogerror(VTPM_LOG_VTPM, "Closing DMI has bad size.");
+ status = TPM_BAD_PARAMETER;
+ goto abort_egress;
+ }
+
+ BSG_UnpackList( param_buf->bytes, 1,
+ BSG_TYPE_UINT32, &dmi_id);
+
+ vtpmloginfo(VTPM_LOG_VTPM, "Closing DMI %d.\n", dmi_id);
+
+ dmi_res = (VTPM_DMI_RESOURCE *) hashtable_search(vtpm_globals->dmi_map,
&dmi_id);
+ if (dmi_res == NULL ) {
+ vtpmlogerror(VTPM_LOG_VTPM, "Trying to close nonexistent DMI.\n");
+ status = TPM_BAD_PARAMETER;
+ goto abort_egress;
+ }
+
+ if (!dmi_res->connected) {
+ vtpmlogerror(VTPM_LOG_VTPM, "Closing non-connected DMI.\n");
+ status = TPM_BAD_PARAMETER;
+ goto abort_egress;
+ }
+
+ // Close Dmi
+ TPMTRYRETURN(close_dmi( dmi_res ));
+
+ status=TPM_SUCCESS;
+ goto egress;
+
+ abort_egress:
+ egress:
+
+ return status;
+}
+
+TPM_RESULT VTPM_Handle_Delete_DMI( const buffer_t *param_buf) {
+
+ TPM_RESULT status=TPM_FAIL;
+ VTPM_DMI_RESOURCE *dmi_res=NULL;
+ UINT32 dmi_id;
+
+ if ((param_buf == NULL) || (buffer_len(param_buf) != sizeof(UINT32)) ) {
+ vtpmlogerror(VTPM_LOG_VTPM, "Closing DMI has bad size.\n");
+ status = TPM_BAD_PARAMETER;
+ goto abort_egress;
+ }
+
+ BSG_UnpackList( param_buf->bytes, 1,
+ BSG_TYPE_UINT32, &dmi_id);
+
+ vtpmloginfo(VTPM_LOG_VTPM, "Deleting DMI %d.\n", dmi_id);
+
+ dmi_res = (VTPM_DMI_RESOURCE *) hashtable_remove(vtpm_globals->dmi_map,
&dmi_id);
+ if (dmi_res == NULL) {
+ vtpmlogerror(VTPM_LOG_VTPM, "Closing non-existent DMI.\n");
+ status = TPM_BAD_PARAMETER;
+ goto abort_egress;
+ }
+
+ //TODO: Automatically delete file dmi_res->NVMLocation
+
+ // Close DMI first
+ TPMTRYRETURN(close_dmi( dmi_res ));
+ free ( dmi_res );
+
+ status=TPM_SUCCESS;
+ goto egress;
+
+ abort_egress:
+ egress:
+
+ return status;
+}
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/manager/securestorage.c
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/manager/securestorage.c Thu Sep 1 10:16:14 2005
@@ -0,0 +1,401 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+//
+// securestorage.c
+//
+// Functions regarding securely storing DMI secrets.
+//
+// ==================================================================
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "tcg.h"
+#include "vtpm_manager.h"
+#include "vtpmpriv.h"
+#include "vtsp.h"
+#include "bsg.h"
+#include "crypto.h"
+#include "hashtable.h"
+#include "hashtable_itr.h"
+#include "buffer.h"
+#include "log.h"
+
+TPM_RESULT VTPM_Handle_Save_NVM(VTPM_DMI_RESOURCE *myDMI,
+ const buffer_t *inbuf,
+ buffer_t *outbuf) {
+
+ TPM_RESULT status = TPM_SUCCESS;
+ symkey_t symkey;
+ buffer_t state_cipher = NULL_BUF,
+ symkey_cipher = NULL_BUF;
+ int fh;
+ long bytes_written;
+ BYTE *sealed_NVM=NULL;
+ UINT32 sealed_NVM_size, i;
+ struct pack_constbuf_t symkey_cipher32, state_cipher32;
+
+ vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Save_NVMing[%d]: 0x", buffer_len(inbuf));
+ for (i=0; i< buffer_len(inbuf); i++)
+ vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", inbuf->bytes[i]);
+ vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
+
+ // Generate a sym key and encrypt state with it
+ TPMTRY(TPM_ENCRYPT_ERROR, Crypto_symcrypto_genkey (&symkey) );
+ TPMTRY(TPM_ENCRYPT_ERROR, Crypto_symcrypto_encrypt (&symkey, inbuf,
&state_cipher) );
+
+ // Encrypt symmetric key
+ TPMTRYRETURN( VTSP_Bind( &vtpm_globals->storageKey,
+ &symkey.key,
+ &symkey_cipher) );
+
+ // Create output blob: symkey_size + symkey_cipher + state_cipher_size +
state_cipher
+
+ symkey_cipher32.size = buffer_len(&symkey_cipher);
+ symkey_cipher32.data = symkey_cipher.bytes;
+
+ state_cipher32.size = buffer_len(&state_cipher);
+ state_cipher32.data = state_cipher.bytes;
+
+ sealed_NVM = (BYTE *) malloc( 2 * sizeof(UINT32) + symkey_cipher32.size +
state_cipher32.size);
+
+ sealed_NVM_size = BSG_PackList(sealed_NVM, 2,
+ BSG_TPM_SIZE32_DATA, &symkey_cipher32,
+ BSG_TPM_SIZE32_DATA, &state_cipher32);
+
+ // Mark DMI Table so new save state info will get pushed to disk on return.
+ vtpm_globals->DMI_table_dirty = TRUE;
+
+ // Write sealed blob off disk from NVMLocation
+ // TODO: How to properly return from these. Do we care if we return failure
+ // after writing the file? We can't get the old one back.
+ // TODO: Backup old file and try and recover that way.
+ fh = open(myDMI->NVMLocation, O_WRONLY | O_CREAT, S_IREAD | S_IWRITE);
+ if ( (bytes_written = write(fh, sealed_NVM, sealed_NVM_size) ) != (long)
sealed_NVM_size) {
+ vtpmlogerror(VTPM_LOG_VTPM, "We just overwrote a DMI_NVM and failed to
finish. %ld/%ld bytes.\n", bytes_written, (long)sealed_NVM_size);
+ status = TPM_IOERROR;
+ goto abort_egress;
+ }
+ close(fh);
+
+ Crypto_SHA1Full (sealed_NVM, sealed_NVM_size, (BYTE *)
&myDMI->NVM_measurement);
+
+ vtpmloginfo(VTPM_LOG_VTPM, "Saved %d bytes of E(symkey) + %d bytes of
E(NVM)\n", buffer_len(&symkey_cipher), buffer_len(&state_cipher));
+ goto egress;
+
+ abort_egress:
+ vtpmlogerror(VTPM_LOG_VTPM, "Failed to load NVM\n.");
+
+ egress:
+
+ buffer_free ( &state_cipher);
+ buffer_free ( &symkey_cipher);
+ free(sealed_NVM);
+ Crypto_symcrypto_freekey (&symkey);
+
+ return status;
+}
+
+
+/* inbuf = null outbuf = sealed blob size, sealed blob.*/
+TPM_RESULT VTPM_Handle_Load_NVM(VTPM_DMI_RESOURCE *myDMI,
+ const buffer_t *inbuf,
+ buffer_t *outbuf) {
+
+ TPM_RESULT status = TPM_SUCCESS;
+ symkey_t symkey;
+ buffer_t state_cipher = NULL_BUF,
+ symkey_clear = NULL_BUF,
+ symkey_cipher = NULL_BUF;
+ struct pack_buf_t symkey_cipher32, state_cipher32;
+
+ UINT32 sealed_NVM_size;
+ BYTE *sealed_NVM = NULL;
+ long fh_size;
+ int fh, stat_ret, i;
+ struct stat file_stat;
+ TPM_DIGEST sealedNVMHash;
+
+ memset(&symkey, 0, sizeof(symkey_t));
+
+ if (myDMI->NVMLocation == NULL) {
+ vtpmlogerror(VTPM_LOG_VTPM, "Unable to load NVM because the file name
NULL.\n");
+ status = TPM_AUTHFAIL;
+ goto abort_egress;
+ }
+
+ //Read sealed blob off disk from NVMLocation
+ fh = open(myDMI->NVMLocation, O_RDONLY);
+ stat_ret = fstat(fh, &file_stat);
+ if (stat_ret == 0)
+ fh_size = file_stat.st_size;
+ else {
+ status = TPM_IOERROR;
+ goto abort_egress;
+ }
+
+ sealed_NVM = (BYTE *) malloc(fh_size);
+ if (read(fh, sealed_NVM, fh_size) != fh_size) {
+ status = TPM_IOERROR;
+ goto abort_egress;
+ }
+ close(fh);
+
+ vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Load_NVMing[%ld]: 0x", fh_size);
+ for (i=0; i< fh_size; i++)
+ vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", sealed_NVM[i]);
+ vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
+
+ sealed_NVM_size = BSG_UnpackList(sealed_NVM, 2,
+ BSG_TPM_SIZE32_DATA, &symkey_cipher32,
+ BSG_TPM_SIZE32_DATA, &state_cipher32);
+
+ TPMTRYRETURN( buffer_init_convert (&symkey_cipher,
+ symkey_cipher32.size,
+ symkey_cipher32.data) );
+
+ TPMTRYRETURN( buffer_init_convert (&state_cipher,
+ state_cipher32.size,
+ state_cipher32.data) );
+
+ Crypto_SHA1Full(sealed_NVM, sealed_NVM_size, (BYTE *) &sealedNVMHash);
+
+ // Verify measurement of sealed blob.
+ if (memcmp(&sealedNVMHash, &myDMI->NVM_measurement, sizeof(TPM_DIGEST)) ) {
+ vtpmlogerror(VTPM_LOG_VTPM, "VTPM LoadNVM NVM measurement check
failed.\n");
+ vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Correct hash: ");
+ for (i=0; i< sizeof(TPM_DIGEST); i++)
+ vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ",
((BYTE*)&myDMI->NVM_measurement)[i]);
+ vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
+
+ vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Measured hash: ");
+ for (i=0; i< sizeof(TPM_DIGEST); i++)
+ vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", ((BYTE*)&sealedNVMHash)[i]);
+ vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
+
+ status = TPM_AUTHFAIL;
+ goto abort_egress;
+ }
+
+ // Decrypt Symmetric Key
+ TPMTRYRETURN( VTSP_Unbind( myDMI->TCSContext,
+ vtpm_globals->storageKeyHandle,
+ &symkey_cipher,
+ (const
TPM_AUTHDATA*)&vtpm_globals->storage_key_usage_auth,
+ &symkey_clear,
+ &(vtpm_globals->keyAuth) ) );
+
+ // create symmetric key using saved bits
+ Crypto_symcrypto_initkey (&symkey, &symkey_clear);
+
+ // Decrypt State
+ TPMTRY(TPM_DECRYPT_ERROR, Crypto_symcrypto_decrypt (&symkey, &state_cipher,
outbuf) );
+
+ goto egress;
+
+ abort_egress:
+ vtpmlogerror(VTPM_LOG_VTPM, "Failed to load NVM\n.");
+
+ egress:
+
+ buffer_free ( &state_cipher);
+ buffer_free ( &symkey_clear);
+ buffer_free ( &symkey_cipher);
+ free( sealed_NVM );
+ Crypto_symcrypto_freekey (&symkey);
+
+ return status;
+}
+
+TPM_RESULT VTPM_SaveService(void) {
+ TPM_RESULT status=TPM_SUCCESS;
+ int fh, dmis=-1;
+
+ BYTE *flat_global;
+ int flat_global_size, bytes_written;
+ UINT32 storageKeySize = buffer_len(&vtpm_globals->storageKeyWrap);
+ struct pack_buf_t storage_key_pack = {storageKeySize,
vtpm_globals->storageKeyWrap.bytes};
+
+ struct hashtable_itr *dmi_itr;
+ VTPM_DMI_RESOURCE *dmi_res;
+
+ UINT32 flat_global_full_size;
+
+ // Global Values needing to be saved
+ flat_global_full_size = 3*sizeof(TPM_DIGEST) + // Auths
+ sizeof(UINT32) + // storagekeysize
+ storageKeySize + // storage key
+ hashtable_count(vtpm_globals->dmi_map) * // num DMIS
+ (sizeof(UINT32) + 2*sizeof(TPM_DIGEST)); // Per DMI info
+
+
+ flat_global = (BYTE *) malloc( flat_global_full_size);
+
+ flat_global_size = BSG_PackList(flat_global, 4,
+ BSG_TPM_AUTHDATA,
&vtpm_globals->owner_usage_auth,
+ BSG_TPM_AUTHDATA,
&vtpm_globals->srk_usage_auth,
+ BSG_TPM_SECRET,
&vtpm_globals->storage_key_usage_auth,
+ BSG_TPM_SIZE32_DATA, &storage_key_pack);
+
+ // Per DMI values to be saved
+ if (hashtable_count(vtpm_globals->dmi_map) > 0) {
+
+ dmi_itr = hashtable_iterator(vtpm_globals->dmi_map);
+ do {
+ dmi_res = (VTPM_DMI_RESOURCE *) hashtable_iterator_value(dmi_itr);
+ dmis++;
+
+ // No need to save dmi0.
+ if (dmi_res->dmi_id == 0)
+ continue;
+
+
+ flat_global_size += BSG_PackList( flat_global + flat_global_size, 3,
+ BSG_TYPE_UINT32, &dmi_res->dmi_id,
+ BSG_TPM_DIGEST,
&dmi_res->NVM_measurement,
+ BSG_TPM_DIGEST,
&dmi_res->DMI_measurement);
+
+ } while (hashtable_iterator_advance(dmi_itr));
+ }
+
+ //FIXME: Once we have a way to protect a TPM key, we should use it to
+ // encrypt this blob. BUT, unless there is a way to ensure the key is
+ // not used by other apps, this encryption is useless.
+ fh = open(STATE_FILE, O_WRONLY | O_CREAT, S_IREAD | S_IWRITE);
+ if (fh == -1) {
+ vtpmlogerror(VTPM_LOG_VTPM, "Unable to open %s file for write.\n",
STATE_FILE);
+ status = TPM_IOERROR;
+ goto abort_egress;
+ }
+
+ if ( (bytes_written = write(fh, flat_global, flat_global_size)) !=
flat_global_size ) {
+ vtpmlogerror(VTPM_LOG_VTPM, "Failed to save service data. %d/%d bytes
written.\n", bytes_written, flat_global_size);
+ status = TPM_IOERROR;
+ goto abort_egress;
+ }
+ vtpm_globals->DMI_table_dirty = FALSE;
+
+ goto egress;
+
+ abort_egress:
+ egress:
+
+ free(flat_global);
+ close(fh);
+
+ vtpmloginfo(VTPM_LOG_VTPM, "Saved VTPM Service state (status = %d, dmis =
%d)\n", (int) status, dmis);
+ return status;
+}
+
+TPM_RESULT VTPM_LoadService(void) {
+
+ TPM_RESULT status=TPM_SUCCESS;
+ int fh, stat_ret, dmis=0;
+ long fh_size = 0, step_size;
+ BYTE *flat_global=NULL;
+ struct pack_buf_t storage_key_pack;
+ UINT32 *dmi_id_key;
+
+ VTPM_DMI_RESOURCE *dmi_res;
+ struct stat file_stat;
+
+ fh = open(STATE_FILE, O_RDONLY );
+ stat_ret = fstat(fh, &file_stat);
+ if (stat_ret == 0)
+ fh_size = file_stat.st_size;
+ else {
+ status = TPM_IOERROR;
+ goto abort_egress;
+ }
+
+ flat_global = (BYTE *) malloc(fh_size);
+
+ if ((long) read(fh, flat_global, fh_size) != fh_size ) {
+ status = TPM_IOERROR;
+ goto abort_egress;
+ }
+
+ // Global Values needing to be saved
+ step_size = BSG_UnpackList( flat_global, 4,
+ BSG_TPM_AUTHDATA, &vtpm_globals->owner_usage_auth,
+ BSG_TPM_AUTHDATA, &vtpm_globals->srk_usage_auth,
+ BSG_TPM_SECRET,
&vtpm_globals->storage_key_usage_auth,
+ BSG_TPM_SIZE32_DATA, &storage_key_pack);
+
+ TPMTRYRETURN(buffer_init(&vtpm_globals->storageKeyWrap, 0, 0) );
+ TPMTRYRETURN(buffer_append_raw(&vtpm_globals->storageKeyWrap,
storage_key_pack.size, storage_key_pack.data) );
+
+ // Per DMI values to be saved
+ while ( step_size < fh_size ){
+ if (fh_size - step_size < (long) (sizeof(UINT32) + 2*sizeof(TPM_DIGEST))) {
+ vtpmlogerror(VTPM_LOG_VTPM, "Encountered %ld extra bytes at end of
manager state.\n", fh_size-step_size);
+ step_size = fh_size;
+ } else {
+ dmi_res = (VTPM_DMI_RESOURCE *) malloc(sizeof(VTPM_DMI_RESOURCE));
+ dmis++;
+
+ dmi_res->connected = FALSE;
+
+ step_size += BSG_UnpackList(flat_global + step_size, 3,
+ BSG_TYPE_UINT32, &dmi_res->dmi_id,
+ BSG_TPM_DIGEST, &dmi_res->NVM_measurement,
+ BSG_TPM_DIGEST, &dmi_res->DMI_measurement);
+
+ // install into map
+ dmi_id_key = (UINT32 *) malloc (sizeof(UINT32));
+ *dmi_id_key = dmi_res->dmi_id;
+ if (!hashtable_insert(vtpm_globals->dmi_map, dmi_id_key, dmi_res)) {
+ status = TPM_FAIL;
+ goto abort_egress;
+ }
+
+ }
+
+ }
+
+ goto egress;
+
+ abort_egress:
+ vtpmlogerror(VTPM_LOG_VTPM, "Failed to save service data\n");
+ egress:
+
+ if (flat_global)
+ free(flat_global);
+ close(fh);
+
+ vtpmloginfo(VTPM_LOG_VTPM, "Previously saved state reloaded (status = %d,
dmis = %d).\n", (int) status, dmis);
+ return status;
+}
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/manager/tpmpassthrough.c
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/manager/tpmpassthrough.c Thu Sep 1 10:16:14 2005
@@ -0,0 +1,110 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+//
+// tpmpassthrough.c
+//
+// Functions regarding passing DMI requests to HWTPM
+//
+// ==================================================================
+
+#include "tcg.h"
+#include "vtpm_manager.h"
+#include "vtpmpriv.h"
+#include "vtsp.h"
+#include "log.h"
+
+TPM_RESULT VTPM_Handle_TPM_Command( VTPM_DMI_RESOURCE *dmi,
+ buffer_t *inbuf,
+ buffer_t *outbuf) {
+
+ TPM_RESULT status = TPM_SUCCESS;
+ TPM_COMMAND_CODE *ord;
+
+ ord = (TPM_COMMAND_CODE *) (inbuf->bytes + sizeof(TPM_TAG) + sizeof(UINT32));
+
+ switch (*ord) {
+
+ // Forbidden for DMI use
+ case TPM_ORD_TakeOwnership:
+ case TPM_ORD_ChangeAuthOwner:
+ case TPM_ORD_DirWriteAuth:
+ case TPM_ORD_DirRead:
+ case TPM_ORD_AuthorizeMigrationKey:
+ case TPM_ORD_CreateMaintenanceArchive:
+ case TPM_ORD_LoadMaintenanceArchive:
+ case TPM_ORD_KillMaintenanceFeature:
+ case TPM_ORD_LoadManuMaintPub:
+ case TPM_ORD_ReadManuMaintPub:
+ case TPM_ORD_SelfTestFull:
+ case TPM_ORD_SelfTestStartup:
+ case TPM_ORD_CertifySelfTest:
+ case TPM_ORD_ContinueSelfTest:
+ case TPM_ORD_GetTestResult:
+ case TPM_ORD_Reset:
+ case TPM_ORD_OwnerClear:
+ case TPM_ORD_DisableOwnerClear:
+ case TPM_ORD_ForceClear:
+ case TPM_ORD_DisableForceClear:
+ case TPM_ORD_GetCapabilityOwner:
+ case TPM_ORD_OwnerSetDisable:
+ case TPM_ORD_PhysicalEnable:
+ case TPM_ORD_PhysicalDisable:
+ case TPM_ORD_SetOwnerInstall:
+ case TPM_ORD_PhysicalSetDeactivated:
+ case TPM_ORD_SetTempDeactivated:
+ case TPM_ORD_CreateEndorsementKeyPair:
+ case TPM_ORD_GetAuditEvent:
+ case TPM_ORD_GetAuditEventSigned:
+ case TPM_ORD_GetOrdinalAuditStatus:
+ case TPM_ORD_SetOrdinalAuditStatus:
+ case TPM_ORD_SetRedirection:
+ case TPM_ORD_FieldUpgrade:
+ case TSC_ORD_PhysicalPresence:
+ status = TPM_DISABLED_CMD;
+ goto abort_egress;
+ break;
+
+ } // End ORD Switch
+
+ // Call TCS with command
+
+ TPMTRY(TPM_IOERROR, VTSP_RawTransmit( dmi->TCSContext,inbuf, outbuf) );
+
+ goto egress;
+
+ abort_egress:
+ vtpmloginfo(VTPM_LOG_VTPM, "TPM Command Failed in tpmpassthrough.\n");
+ egress:
+
+ return status;
+}
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/manager/vtpm_manager.c
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/manager/vtpm_manager.c Thu Sep 1 10:16:14 2005
@@ -0,0 +1,735 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+//
+// vtpm_manager.c
+//
+// This file will house the main logic of the VTPM Manager
+//
+// ==================================================================
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+
+#ifndef VTPM_MULTI_VM
+#include <pthread.h>
+#include <errno.h>
+#include <aio.h>
+#include <time.h>
+#endif
+
+#include "vtpm_manager.h"
+#include "vtpmpriv.h"
+#include "vtsp.h"
+#include "bsg.h"
+#include "hashtable.h"
+#include "hashtable_itr.h"
+
+#include "log.h"
+#include "buffer.h"
+
+VTPM_GLOBALS *vtpm_globals=NULL;
+
+#ifdef VTPM_MULTI_VM
+ #define vtpmhandlerloginfo(module,fmt,args...) vtpmloginfo (module, fmt,
##args );
+ #define vtpmhandlerloginfomore(module,fmt,args...) vtpmloginfomore (module,
fmt, ##args );
+ #define vtpmhandlerlogerror(module,fmt,args...) vtpmlogerror (module, fmt,
##args );
+#else
+ #define vtpmhandlerloginfo(module,fmt,args...) vtpmloginfo (module, "[%d]: "
fmt, threadType, ##args );
+ #define vtpmhandlerloginfomore(module,fmt,args...) vtpmloginfomore (module,
fmt, ##args );
+ #define vtpmhandlerlogerror(module,fmt,args...) vtpmlogerror (module, "[%d]:
" fmt, threadType, ##args );
+#endif
+
+// --------------------------- Static Auths --------------------------
+#ifdef USE_FIXED_SRK_AUTH
+
+static BYTE FIXED_SRK_AUTH[20] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff};
+
+static BYTE FIXED_EK_AUTH[20] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff};
+
+#endif
+
+// -------------------------- Hash table functions --------------------
+
+static unsigned int hashfunc32(void *ky) {
+ return (* (UINT32 *) ky);
+}
+
+static int equals32(void *k1, void *k2) {
+ return (*(UINT32 *) k1 == *(UINT32 *) k2);
+}
+
+// --------------------------- Functions ------------------------------
+
+TPM_RESULT VTPM_Create_Service(){
+
+ TPM_RESULT status = TPM_SUCCESS;
+
+ // Generate Auth's for SRK & Owner
+#ifdef USE_FIXED_SRK_AUTH
+ memcpy(vtpm_globals->owner_usage_auth, FIXED_SRK_AUTH, sizeof(TPM_AUTHDATA));
+ memcpy(vtpm_globals->srk_usage_auth, FIXED_EK_AUTH, sizeof(TPM_AUTHDATA));
+#else
+ Crypto_GetRandom(vtpm_globals->owner_usage_auth, sizeof(TPM_AUTHDATA) );
+ Crypto_GetRandom(vtpm_globals->srk_usage_auth, sizeof(TPM_AUTHDATA) );
+#endif
+
+ // Take Owership of TPM
+ CRYPTO_INFO ek_cryptoInfo;
+
+ vtpmloginfo(VTPM_LOG_VTPM, "Attempting Pubek Read. NOTE: Failure is ok.\n");
+ status = VTSP_ReadPubek(vtpm_globals->manager_tcs_handle, &ek_cryptoInfo);
+
+ // If we can read PubEK then there is no owner and we should take it.
+ if (status == TPM_SUCCESS) {
+ TPMTRYRETURN(VTSP_TakeOwnership(vtpm_globals->manager_tcs_handle,
+ (const
TPM_AUTHDATA*)&vtpm_globals->owner_usage_auth,
+ (const
TPM_AUTHDATA*)&vtpm_globals->srk_usage_auth,
+ &ek_cryptoInfo,
+ &vtpm_globals->keyAuth));
+
+ TPMTRYRETURN(VTSP_DisablePubekRead(vtpm_globals->manager_tcs_handle,
+ (const
TPM_AUTHDATA*)&vtpm_globals->owner_usage_auth,
+ &vtpm_globals->keyAuth));
+ }
+
+ // Generate storage key's auth
+ Crypto_GetRandom( &vtpm_globals->storage_key_usage_auth,
+ sizeof(TPM_AUTHDATA) );
+
+ TCS_AUTH osap;
+ TPM_AUTHDATA sharedsecret;
+
+ TPMTRYRETURN( VTSP_OSAP(vtpm_globals->manager_tcs_handle,
+ TPM_ET_SRK,
+ 0,
+ (const TPM_AUTHDATA*)&vtpm_globals->srk_usage_auth,
+ &sharedsecret,
+ &osap) );
+
+ TPMTRYRETURN( VTSP_CreateWrapKey( vtpm_globals->manager_tcs_handle,
+ TPM_KEY_BIND,
+ (const
TPM_AUTHDATA*)&vtpm_globals->storage_key_usage_auth,
+ TPM_SRK_KEYHANDLE,
+ (const TPM_AUTHDATA*)&sharedsecret,
+ &vtpm_globals->storageKeyWrap,
+ &osap) );
+
+ vtpm_globals->keyAuth.fContinueAuthSession = TRUE;
+
+ goto egress;
+
+ abort_egress:
+ exit(1);
+
+ egress:
+ vtpmloginfo(VTPM_LOG_VTPM, "New VTPM Service initialized (Status = %d).\n",
status);
+ return status;
+
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+#ifdef VTPM_MULTI_VM
+int VTPM_Service_Handler(){
+#else
+void *VTPM_Service_Handler(void *threadTypePtr){
+#endif
+ TPM_RESULT status = TPM_FAIL; // Should never return
+ UINT32 dmi, in_param_size, cmd_size, out_param_size,
out_message_size, out_message_size_full, dmi_cmd_size;
+ BYTE *cmd_header, *in_param, *out_message, *dmi_cmd;
+ buffer_t *command_buf=NULL, *result_buf=NULL;
+ TPM_TAG tag;
+ TPM_COMMAND_CODE ord;
+ VTPM_DMI_RESOURCE *dmi_res;
+ int size_read, size_write, i;
+
+#ifndef VTPM_MULTI_VM
+ int threadType = *(int *) threadTypePtr;
+
+ // async io structures
+ struct aiocb dmi_aio;
+ struct aiocb *dmi_aio_a[1];
+ dmi_aio_a[0] = &dmi_aio;
+#endif
+
+#ifdef DUMMY_BACKEND
+ int dummy_rx;
+#endif
+
+ // TODO: Reinsert ifdefs to enable support for MULTI-VM
+
+ cmd_header = (BYTE *) malloc(VTPM_COMMAND_HEADER_SIZE_SRV);
+ command_buf = (buffer_t *) malloc(sizeof(buffer_t));
+ result_buf = (buffer_t *) malloc(sizeof(buffer_t));
+
+#ifndef VTPM_MULTI_VM
+ TPM_RESULT *ret_value = (TPM_RESULT *) malloc(sizeof(TPM_RESULT));
+#endif
+
+ int *tx_fh, *rx_fh;
+
+#ifdef VTPM_MULTI_VM
+ rx_fh = &vtpm_globals->be_fh;
+#else
+ if (threadType == BE_LISTENER_THREAD) {
+#ifdef DUMMY_BACKEND
+ dummy_rx = -1;
+ rx_fh = &dummy_rx;
+#else
+ rx_fh = &vtpm_globals->be_fh;
+#endif
+ } else { // DMI_LISTENER_THREAD
+ rx_fh = &vtpm_globals->vtpm_rx_fh;
+ }
+#endif
+
+#ifndef VTPM_MULTI_VM
+ int fh;
+ if (threadType == BE_LISTENER_THREAD) {
+ tx_fh = &vtpm_globals->be_fh;
+ if ( (fh = open(GUEST_RX_FIFO, O_RDWR)) == -1) {
+ if ( mkfifo(GUEST_RX_FIFO, S_IWUSR | S_IRUSR ) ){
+ *ret_value = TPM_FAIL;
+ pthread_exit(ret_value);
+ }
+ } else
+ close(fh);
+
+ } else { // else DMI_LISTENER_THREAD
+ // tx_fh will be set once the DMI is identified
+ // But we need to make sure the read pip is created.
+ if ( (fh = open(VTPM_RX_FIFO, O_RDWR)) == -1) {
+ if ( mkfifo(VTPM_RX_FIFO, S_IWUSR | S_IRUSR ) ){
+ *ret_value = TPM_FAIL;
+ pthread_exit(ret_value);
+ }
+ } else
+ close(fh);
+
+ }
+#endif
+
+ while(1) {
+
+ if (threadType == BE_LISTENER_THREAD) {
+ vtpmhandlerloginfo(VTPM_LOG_VTPM, "Waiting for Guest requests & ctrl
messages.\n");
+ } else
+ vtpmhandlerloginfo(VTPM_LOG_VTPM, "Waiting for DMI messages.\n");
+
+
+ if (*rx_fh < 0) {
+ if (threadType == BE_LISTENER_THREAD)
+#ifdef DUMMY_BACKEND
+ *rx_fh = open("/tmp/in.fifo", O_RDWR);
+#else
+ *rx_fh = open(VTPM_BE_DEV, O_RDWR);
+#endif
+ else // DMI Listener
+ *rx_fh = open(VTPM_RX_FIFO, O_RDWR);
+
+ }
+
+ if (*rx_fh < 0) {
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Can't open inbound fh.\n");
+#ifdef VTPM_MULTI_VM
+ return TPM_IOERROR;
+#else
+ *ret_value = TPM_IOERROR;
+ pthread_exit(ret_value);
+#endif
+ }
+
+ size_read = read(*rx_fh, cmd_header, VTPM_COMMAND_HEADER_SIZE_SRV);
+ if (size_read > 0) {
+ vtpmhandlerloginfo(VTPM_LOG_VTPM_DEEP, "RECV[%d}: 0x", size_read);
+ for (i=0; i<size_read; i++)
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ",
cmd_header[i]);
+ } else {
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Can't read from BE. Aborting... \n");
+ close(*rx_fh);
+ *rx_fh = -1;
+ goto abort_command;
+ }
+
+ if (size_read < (int) VTPM_COMMAND_HEADER_SIZE_SRV) {
+ vtpmhandlerloginfo(VTPM_LOG_VTPM_DEEP, "\n");
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Command shorter than normal header
(%d bytes). Aborting...\n", size_read);
+ goto abort_command;
+ }
+
+ BSG_UnpackList(cmd_header, 4,
+ BSG_TYPE_UINT32, &dmi,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, &in_param_size,
+ BSG_TPM_COMMAND_CODE, &ord );
+
+ // Note that in_param_size is in the client's context
+ cmd_size = in_param_size - VTPM_COMMAND_HEADER_SIZE_CLT;
+ if (cmd_size > 0) {
+ in_param = (BYTE *) malloc(cmd_size);
+ size_read = read( *rx_fh, in_param, cmd_size);
+ if (size_read > 0) {
+ for (i=0; i<size_read; i++)
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", in_param[i]);
+
+ } else {
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Error reading from BE. Aborting...
\n");
+ close(*rx_fh);
+ *rx_fh = -1;
+ goto abort_command;
+ }
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
+
+ if (size_read < (int) cmd_size) {
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Command read(%d) is shorter than
header indicates(%d). Aborting...\n", size_read, cmd_size);
+ goto abort_command;
+ }
+ } else {
+ in_param = NULL;
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
+ }
+
+ if ((threadType != BE_LISTENER_THREAD) && (dmi == 0)) {
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Attempt to access dom0 commands from
DMI interface. Aborting...\n");
+ goto abort_command;
+ }
+
+ dmi_res = (VTPM_DMI_RESOURCE *) hashtable_search(vtpm_globals->dmi_map,
&dmi);
+ if (dmi_res == NULL) {
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Attempted access to non-existent DMI
in domain: %d. Aborting...\n", dmi);
+ goto abort_command;
+ }
+ if (!dmi_res->connected) {
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Attempted access to disconnected DMI
in domain: %d. Aborting...\n", dmi);
+ goto abort_command;
+ }
+
+ if (threadType != BE_LISTENER_THREAD)
+ tx_fh = &dmi_res->vtpm_tx_fh;
+ // else we set this before the while loop since it doesn't change.
+
+ if ( (buffer_init_convert(command_buf, cmd_size, in_param) != TPM_SUCCESS)
||
+ (buffer_init(result_buf, 0, 0) != TPM_SUCCESS) ) {
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Failed to setup buffers.
Aborting...\n");
+ goto abort_command;
+ }
+
+ // Dispatch it as either control or user request.
+ if (tag == VTPM_TAG_REQ) {
+ if (dmi_res->dmi_id == VTPM_CTL_DM){
+ switch (ord) {
+ case VTPM_ORD_OPEN:
+ status = VTPM_Handle_New_DMI(command_buf);
+ break;
+
+ case VTPM_ORD_CLOSE:
+ status = VTPM_Handle_Close_DMI(command_buf);
+ break;
+
+ case VTPM_ORD_DELETE:
+ status = VTPM_Handle_Delete_DMI(command_buf);
+ break;
+ default:
+ status = TPM_BAD_ORDINAL;
+ } // switch
+ } else {
+
+ switch (ord) {
+ case VTPM_ORD_SAVENVM:
+ status= VTPM_Handle_Save_NVM(dmi_res,
+ command_buf,
+ result_buf);
+ break;
+ case VTPM_ORD_LOADNVM:
+ status= VTPM_Handle_Load_NVM(dmi_res,
+ command_buf,
+ result_buf);
+ break;
+
+ case VTPM_ORD_TPMCOMMAND:
+ status= VTPM_Handle_TPM_Command(dmi_res,
+ command_buf,
+ result_buf);
+ break;
+
+ default:
+ status = TPM_BAD_ORDINAL;
+ } // switch
+ }
+ } else { // This is not a VTPM Command at all
+
+ if (threadType == BE_LISTENER_THREAD) {
+ if (dmi == 0) {
+ // This usually indicates a FE/BE driver.
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Illegal use of TPM command from
dom0\n");
+ status = TPM_FAIL;
+ } else {
+ vtpmhandlerloginfo(VTPM_LOG_VTPM, "Forwarding command to DMI.\n");
+
+ if (dmi_res->guest_tx_fh < 0)
+ dmi_res->guest_tx_fh = open(dmi_res->guest_tx_fname, O_WRONLY |
O_NONBLOCK);
+
+ if (dmi_res->guest_tx_fh < 0){
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "VTPM ERROR: Can't open outbound
fh to dmi.\n");
+ status = TPM_IOERROR;
+ goto abort_with_error;
+ }
+
+ //Note: Send message + dmi_id
+ if (cmd_size) {
+ dmi_cmd = (BYTE *) malloc(VTPM_COMMAND_HEADER_SIZE_SRV + cmd_size);
+ dmi_cmd_size = VTPM_COMMAND_HEADER_SIZE_SRV + cmd_size;
+ memcpy(dmi_cmd, cmd_header, VTPM_COMMAND_HEADER_SIZE_SRV);
+ memcpy(dmi_cmd + VTPM_COMMAND_HEADER_SIZE_SRV, in_param, cmd_size);
+ size_write = write(dmi_res->guest_tx_fh, dmi_cmd, dmi_cmd_size);
+
+ if (size_write > 0) {
+ vtpmhandlerloginfo(VTPM_LOG_VTPM_DEEP, "SENT (DMI): 0x");
+ for (i=0; i<VTPM_COMMAND_HEADER_SIZE_SRV + cmd_size; i++) {
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", dmi_cmd[i]);
+ }
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
+ } else {
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Error writing to DMI.
Aborting... \n");
+ close(dmi_res->guest_tx_fh);
+ dmi_res->guest_tx_fh = -1;
+ status = TPM_IOERROR;
+ goto abort_with_error;
+ }
+ free(dmi_cmd);
+ } else {
+ dmi_cmd_size = VTPM_COMMAND_HEADER_SIZE_SRV;
+ size_write = write(dmi_res->guest_tx_fh, cmd_header,
VTPM_COMMAND_HEADER_SIZE_SRV );
+ if (size_write > 0) {
+ for (i=0; i<VTPM_COMMAND_HEADER_SIZE_SRV; i++)
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ",
cmd_header[i]);
+
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
+ } else {
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Error writing to DMI.
Aborting... \n");
+ close(dmi_res->guest_tx_fh);
+ dmi_res->guest_tx_fh = -1;
+ status = TPM_IOERROR;
+ goto abort_with_error;
+ }
+ }
+
+ if (size_write != (int) dmi_cmd_size)
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Could not write entire command
to DMI (%d/%d)\n", size_write, dmi_cmd_size);
+ buffer_free(command_buf);
+
+ if (vtpm_globals->guest_rx_fh < 0)
+ vtpm_globals->guest_rx_fh = open(GUEST_RX_FIFO, O_RDONLY);
+
+ if (vtpm_globals->guest_rx_fh < 0){
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Can't open inbound fh to
dmi.\n");
+ status = TPM_IOERROR;
+ goto abort_with_error;
+ }
+
+ size_read = read( vtpm_globals->guest_rx_fh, cmd_header,
VTPM_COMMAND_HEADER_SIZE_SRV);
+ if (size_read > 0) {
+ vtpmhandlerloginfo(VTPM_LOG_VTPM_DEEP, "RECV (DMI): 0x");
+ for (i=0; i<size_read; i++)
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", cmd_header[i]);
+
+ } else {
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Error reading from DMI.
Aborting... \n");
+ close(vtpm_globals->guest_rx_fh);
+ vtpm_globals->guest_rx_fh = -1;
+ status = TPM_IOERROR;
+ goto abort_with_error;
+ }
+
+ if (size_read < (int) VTPM_COMMAND_HEADER_SIZE_SRV) {
+ //vtpmdeepsublog("\n");
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Command from DMI shorter than
normal header. Aborting...\n");
+ status = TPM_IOERROR;
+ goto abort_with_error;
+ }
+
+ BSG_UnpackList(cmd_header, 4,
+ BSG_TYPE_UINT32, &dmi,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, &in_param_size,
+ BSG_TPM_COMMAND_CODE, &status );
+
+ // Note that in_param_size is in the client's context
+ cmd_size = in_param_size - VTPM_COMMAND_HEADER_SIZE_CLT;
+ if (cmd_size > 0) {
+ in_param = (BYTE *) malloc(cmd_size);
+ size_read = read( vtpm_globals->guest_rx_fh, in_param, cmd_size);
+ if (size_read > 0) {
+ for (i=0; i<size_read; i++)
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", in_param[i]);
+
+ } else {
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Error reading from BE.
Aborting... \n");
+ close(vtpm_globals->guest_rx_fh);
+ vtpm_globals->guest_rx_fh = -1;
+ status = TPM_IOERROR;
+ goto abort_with_error;
+ }
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM, "\n");
+
+ if (size_read < (int)cmd_size) {
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM, "\n");
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Command read(%d) from DMI is
shorter than header indicates(%d). Aborting...\n", size_read, cmd_size);
+ status = TPM_IOERROR;
+ goto abort_with_error;
+ }
+ } else {
+ in_param = NULL;
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM, "\n");
+ }
+
+ if (buffer_init_convert(result_buf, cmd_size, in_param) !=
TPM_SUCCESS) {
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Failed to setup buffers.
Aborting...\n");
+ status = TPM_FAIL;
+ goto abort_with_error;
+ }
+
+ vtpmhandlerloginfo(VTPM_LOG_VTPM, "Sending DMI's response to
guest.\n");
+ } // end else for if (dmi==0)
+
+ } else { // This is a DMI lister thread. Thus this is from a DMI
+#ifdef VTPM_MULTI_VM
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Attempt to use unsupported direct
access to TPM.\n");
+ vtpmhandlerloginfo(VTPM_LOG_VTPM_DEEP, "Bad Command. dmi:%d, tag:%d,
size:%d, ord:%d, Params: ", dmi, tag, in_param_size, ord);
+ for (UINT32 q=0; q<cmd_size; q++)
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", in_param[q]);
+
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
+
+ status = TPM_FAIL;
+#else
+
+#endif
+ } // end else for if BE Listener
+ } // end else for is VTPM Command
+
+ // Send response to Backend
+ if (*tx_fh < 0) {
+ if (threadType == BE_LISTENER_THREAD)
+#ifdef DUMMY_BACKEND
+ *tx_fh = open("/tmp/out.fifo", O_RDWR);
+#else
+ *tx_fh = open(VTPM_BE_DEV, O_RDWR);
+#endif
+ else // DMI Listener
+ *tx_fh = open(dmi_res->vtpm_tx_fname, O_WRONLY);
+ }
+
+ if (*tx_fh < 0) {
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "VTPM ERROR: Can't open outbound
fh.\n");
+#ifdef VTPM_MULTI_VM
+ return TPM_IOERROR;
+#else
+ *ret_value = TPM_IOERROR;
+ pthread_exit(ret_value);
+#endif
+ }
+
+ abort_with_error:
+ // Prepend VTPM header with destination DM stamped
+ out_param_size = buffer_len(result_buf);
+ out_message_size = VTPM_COMMAND_HEADER_SIZE_CLT + out_param_size;
+ out_message_size_full = VTPM_COMMAND_HEADER_SIZE_SRV + out_param_size;
+ out_message = (BYTE *) malloc (out_message_size_full);
+
+ BSG_PackList(out_message, 4,
+ BSG_TYPE_UINT32, (BYTE *) &dmi,
+ BSG_TPM_TAG, (BYTE *) &tag,
+ BSG_TYPE_UINT32, (BYTE *) &out_message_size,
+ BSG_TPM_RESULT, (BYTE *) &status);
+
+ if (buffer_len(result_buf) > 0)
+ memcpy(out_message + VTPM_COMMAND_HEADER_SIZE_SRV, result_buf->bytes,
out_param_size);
+
+
+ //Note: Send message + dmi_id
+ size_write = write(*tx_fh, out_message, out_message_size_full );
+ if (size_write > 0) {
+ vtpmhandlerloginfo(VTPM_LOG_VTPM_DEEP, "SENT: 0x");
+ for (i=0; i < out_message_size_full; i++)
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", out_message[i]);
+
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
+ } else {
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Error writing to BE. Aborting...
\n");
+ close(*tx_fh);
+ *tx_fh = -1;
+ goto abort_command;
+ }
+ free(out_message);
+
+ if (size_write < (int)out_message_size_full) {
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Unable to write full command to BE
(%d/%d)\n", size_write, out_message_size_full);
+ goto abort_command;
+ }
+
+ abort_command:
+ //free buffers
+ bzero(cmd_header, VTPM_COMMAND_HEADER_SIZE_SRV);
+ //free(in_param); // This was converted to command_buf. No need to free
+ if (command_buf != result_buf)
+ buffer_free(result_buf);
+
+ buffer_free(command_buf);
+
+#ifndef VTPM_MULTI_VM
+ if (threadType != BE_LISTENER_THREAD) {
+#endif
+ if ( (vtpm_globals->DMI_table_dirty) &&
+ (VTPM_SaveService() != TPM_SUCCESS) ) {
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "ERROR: Unable to save manager
data.\n");
+ }
+#ifndef VTPM_MULTI_VM
+ }
+#endif
+
+ } // End while(1)
+
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+TPM_RESULT VTPM_Init_Service() {
+ TPM_RESULT status = TPM_FAIL;
+ BYTE *randomsead;
+ UINT32 randomsize;
+
+ if ((vtpm_globals = (VTPM_GLOBALS *) malloc(sizeof(VTPM_GLOBALS))) == NULL){
+ status = TPM_FAIL;
+ goto abort_egress;
+ }
+ memset(vtpm_globals, 0, sizeof(VTPM_GLOBALS));
+ vtpm_globals->be_fh = -1;
+
+#ifndef VTPM_MULTI_VM
+ vtpm_globals->vtpm_rx_fh = -1;
+ vtpm_globals->guest_rx_fh = -1;
+#endif
+ if ((vtpm_globals->dmi_map = create_hashtable(10, hashfunc32, equals32)) ==
NULL){
+ status = TPM_FAIL;
+ goto abort_egress;
+ }
+
+ vtpm_globals->DMI_table_dirty = FALSE;
+
+ // Create new TCS Object
+ vtpm_globals->manager_tcs_handle = 0;
+
+ TPMTRYRETURN(TCS_create());
+
+ // Create TCS Context for service
+ TPMTRYRETURN( TCS_OpenContext(&vtpm_globals->manager_tcs_handle ) );
+
+ TPMTRYRETURN( TCSP_GetRandom(vtpm_globals->manager_tcs_handle,
+
&randomsize,
+
&randomsead));
+
+ Crypto_Init(randomsead, randomsize);
+ TPMTRYRETURN( TCS_FreeMemory (vtpm_globals->manager_tcs_handle,
randomsead));
+
+ // Create OIAP session for service's authorized commands
+ TPMTRYRETURN( VTSP_OIAP( vtpm_globals->manager_tcs_handle,
+ &vtpm_globals->keyAuth) );
+ vtpm_globals->keyAuth.fContinueAuthSession = TRUE;
+
+ // If failed, create new Service.
+ if (VTPM_LoadService() != TPM_SUCCESS)
+ TPMTRYRETURN( VTPM_Create_Service() );
+
+
+ //Load Storage Key
+ TPMTRYRETURN( VTSP_LoadKey( vtpm_globals->manager_tcs_handle,
+ TPM_SRK_KEYHANDLE,
+ &vtpm_globals->storageKeyWrap,
+ (const
TPM_AUTHDATA*)&vtpm_globals->srk_usage_auth,
+ &vtpm_globals->storageKeyHandle,
+ &vtpm_globals->keyAuth,
+ &vtpm_globals->storageKey) );
+
+ // Create entry for Dom0 for control messages
+ TPMTRYRETURN( VTPM_Handle_New_DMI(NULL) );
+
+ // --------------------- Command handlers ---------------------------
+
+ goto egress;
+
+ abort_egress:
+ egress:
+
+ return(status);
+}
+
+void VTPM_Stop_Service() {
+ VTPM_DMI_RESOURCE *dmi_res;
+ struct hashtable_itr *dmi_itr;
+
+ // Close all the TCS contexts. TCS should evict keys based on this
+ if (hashtable_count(vtpm_globals->dmi_map) > 0) {
+ dmi_itr = hashtable_iterator(vtpm_globals->dmi_map);
+ do {
+ dmi_res = (VTPM_DMI_RESOURCE *) hashtable_iterator_value(dmi_itr);
+ if (dmi_res->connected)
+ if (close_dmi( dmi_res ) != TPM_SUCCESS)
+ vtpmlogerror(VTPM_LOG_VTPM, "Failed to
close dmi %d properly.\n", dmi_res->dmi_id);
+
+ } while (hashtable_iterator_advance(dmi_itr));
+ free (dmi_itr);
+ }
+
+
+ TCS_CloseContext(vtpm_globals->manager_tcs_handle);
+
+ if ( (vtpm_globals->DMI_table_dirty) &&
+ (VTPM_SaveService() != TPM_SUCCESS) )
+ vtpmlogerror(VTPM_LOG_VTPM, "Unable to save manager data.\n");
+
+ hashtable_destroy(vtpm_globals->dmi_map, 1);
+ free(vtpm_globals);
+
+ close(vtpm_globals->be_fh);
+ Crypto_Exit();
+
+ vtpmloginfo(VTPM_LOG_VTPM, "VTPM Manager stopped.\n");
+}
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/manager/vtpm_manager.h
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/manager/vtpm_manager.h Thu Sep 1 10:16:14 2005
@@ -0,0 +1,137 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+//
+// vtpm_manager.h
+//
+// Public Interface header for VTPM Manager
+//
+// ==================================================================
+
+#ifndef __VTPM_MANAGER_H__
+#define __VTPM_MANAGER_H__
+
+#include "tcg.h"
+
+#define VTPM_TAG_REQ 0x01c1
+#define VTPM_TAG_RSP 0x01c4
+#define COMMAND_BUFFER_SIZE 4096
+
+// Header sizes. Note Header MAY include the DMI
+#define VTPM_COMMAND_HEADER_SIZE_SRV ( sizeof(UINT32) + sizeof(TPM_TAG) +
sizeof(UINT32) + sizeof(TPM_COMMAND_CODE))
+#define VTPM_COMMAND_HEADER_SIZE_CLT ( sizeof(TPM_TAG) +
sizeof(UINT32) + sizeof(TPM_COMMAND_CODE))
+
+// ********************** Public Functions *************************
+TPM_RESULT VTPM_Init_Service(); // Start VTPM Service
+void VTPM_Stop_Service(); // Stop VTPM Service
+#ifdef VTPM_MULTI_VM
+int VTPM_Service_Handler();
+#else
+void *VTPM_Service_Handler(void *threadTypePtr);
+#endif
+
+//************************ Command Codes ****************************
+#define VTPM_ORD_OPEN 1 // ULM Creates New DMI
+#define VTPM_ORD_CLOSE 2 // ULM Closes a DMI
+#define VTPM_ORD_DELETE 3 // ULM Permemently Deletes DMI
+#define VTPM_ORD_SAVENVM 4 // DMI requests Secrets Unseal
+#define VTPM_ORD_LOADNVM 5 // DMI requests Secrets Saved
+#define VTPM_ORD_TPMCOMMAND 6 // DMI issues HW TPM Command
+
+//************************ Return Codes ****************************
+#define VTPM_SUCCESS 0
+#define VTPM_FAIL 1
+#define VTPM_UNSUPPORTED 2
+#define VTPM_FORBIDDEN 3
+#define VTPM_RESTORE_CONTEXT_FAILED 4
+#define VTPM_INVALID_REQUEST 5
+
+/******************* Command Parameter API *************************
+
+VTPM Command Format
+ dmi: 4 bytes // Source of message.
+ // WARNING: This is prepended by the channel.
+ // Thus it is received by VTPM Manager,
+ // but not sent by DMI
+ tpm tag: 2 bytes
+ command size: 4 bytes // Size of command including header but not DMI
+ ord: 4 bytes // Command ordinal above
+ parameters: size - 10 bytes // Command Parameter
+
+VTPM Response Format
+ tpm tag: 2 bytes
+ response_size: 4 bytes
+ status: 4 bytes
+ parameters: size - 10 bytes
+
+
+VTPM_Open:
+ Input Parameters:
+ Domain_type: 1 byte
+ domain_id: 4 bytes
+ instance_id: 4 bytes
+ Output Parameters:
+ None
+
+VTPM_Close
+ Input Parameters:
+ instance_id: 4 bytes
+ Output Parameters:
+ None
+
+VTPM_Delete
+ Input Parameters:
+ instance_id: 4 bytes
+ Output Parameters:
+ None
+
+VTPM_SaveNVM
+ Input Parameters:
+ data: n bytes (Header indicates size of data)
+ Output Parameters:
+ None
+
+VTPM_LoadNVM
+ Input Parameters:
+ None
+ Output Parameters:
+ data: n bytes (Header indicates size of data)
+
+VTPM_TPMCommand
+ Input Parameters:
+ TPM Command Byte Stream: n bytes
+ Output Parameters:
+ TPM Reponse Byte Stream: n bytes
+
+*********************************************************************/
+
+#endif //_VTPM_MANAGER_H_
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/manager/vtpmd.c
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/manager/vtpmd.c Thu Sep 1 10:16:14 2005
@@ -0,0 +1,134 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+//
+// vtpmd.c
+//
+// Application
+//
+// ===================================================================
+
+#include <stdio.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include "vtpm_manager.h"
+#include "vtpmpriv.h"
+#include "tcg.h"
+#include "log.h"
+
+#ifndef VTPM_MULTI_VM
+ #include <pthread.h>
+#endif
+
+void signal_handler(int reason) {
+#ifndef VTPM_MULTI_VM
+
+ if (pthread_equal(pthread_self(), vtpm_globals->master_pid)) {
+ if (reason >= 0) { // Reason is a signal
+ vtpmloginfo(VTPM_LOG_VTPM, "VTPM Manager shutting down for signal
%d.\n", reason);
+ } else {// Reason is a TPM_RESULT * -1
+ vtpmloginfo(VTPM_LOG_VTPM,"VTPM Manager shuting down for: %s\n",
tpm_get_error_name(-1 * reason) );
+ }
+
+ return;
+ } else {
+ vtpmloginfo(VTPM_LOG_VTPM, "Child shutting down\n");
+ pthread_exit(NULL);
+ }
+#else
+ VTPM_Stop_Service();
+ exit(-1);
+#endif
+}
+
+struct sigaction ctl_c_handler;
+
+int main(int argc, char **argv) {
+
+ vtpmloginfo(VTPM_LOG_VTPM, "Starting VTPM.\n");
+
+ if (VTPM_Init_Service() != TPM_SUCCESS) {
+ vtpmlogerror(VTPM_LOG_VTPM, "Closing vtpmd due to error during
startup.\n");
+ return -1;
+ }
+
+ ctl_c_handler.sa_handler = signal_handler;
+ sigemptyset(&ctl_c_handler.sa_mask);
+ ctl_c_handler.sa_flags = 0;
+
+ if (sigaction(SIGINT, &ctl_c_handler, NULL) == -1)
+ vtpmlogerror(VTPM_LOG_VTPM, "Could not install SIGINT handler. Ctl+break
will not stop service gently.\n");
+
+ // For easier debuggin with gdb
+ if (sigaction(SIGHUP, &ctl_c_handler, NULL) == -1)
+ vtpmlogerror(VTPM_LOG_VTPM, "Could not install SIGHUP handler. Ctl+break
will not stop service gently.\n");
+
+#ifdef VTPM_MULTI_VM
+ TPM_RESULT status = VTPM_Service_Handler();
+
+ if (status != TPM_SUCCESS)
+ vtpmlogerror(VTPM_LOG_VTPM, "VTPM Manager exited with status %s. It never
should exit.\n", tpm_get_error_name(status));
+
+ return -1;
+#else
+ sigset_t sig_mask;
+
+ sigemptyset(&sig_mask);
+ sigaddset(&sig_mask, SIGPIPE);
+ sigprocmask(SIG_BLOCK, &sig_mask, NULL);
+ //pthread_mutex_init(&vtpm_globals->dmi_mutex, NULL);
+ pthread_t be_thread, dmi_thread;
+ int betype_be, dmitype_dmi;
+
+ vtpm_globals->master_pid = pthread_self();
+
+ betype_be = BE_LISTENER_THREAD;
+ if (pthread_create(&be_thread, NULL, VTPM_Service_Handler, &betype_be) != 0)
{
+ vtpmlogerror(VTPM_LOG_VTPM, "Failed to launch BE Thread.\n");
+ exit(-1);
+ }
+
+ dmitype_dmi = DMI_LISTENER_THREAD;
+ if (pthread_create(&dmi_thread, NULL, VTPM_Service_Handler, &dmitype_dmi) !=
0) {
+ vtpmlogerror(VTPM_LOG_VTPM, "Failed to launch DMI Thread.\n");
+ exit(-1);
+ }
+
+ //Join the other threads until exit time.
+ pthread_join(be_thread, NULL);
+ pthread_join(dmi_thread, NULL);
+
+ VTPM_Stop_Service();
+ return 0;
+#endif
+}
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/manager/vtpmpriv.h
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/manager/vtpmpriv.h Thu Sep 1 10:16:14 2005
@@ -0,0 +1,151 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+//
+// vtpmpriv.h
+//
+// Structures and functions private to the manager
+//
+// ==================================================================
+
+#ifndef __VTPMPRIV_H__
+#define __VTPMPRIV_H__
+
+#include "tcg.h"
+#include "tcs.h"
+#include "buffer.h"
+#include "crypto.h"
+
+#define STATE_FILE "/var/vtpm/VTPM"
+#define DMI_NVM_FILE "/var/vtpm/vtpm_dm_%d.data"
+#define VTPM_BE_DEV "/dev/vtpm"
+#define VTPM_CTL_DM 0
+
+#ifndef VTPM_MUTLI_VM
+ #include <sys/types.h>
+ #define GUEST_TX_FIFO "/var/vtpm/fifos/guest-to-%d.fifo"
+ #define GUEST_RX_FIFO "/var/vtpm/fifos/guest-from-all.fifo"
+
+ #define VTPM_TX_FIFO "/var/vtpm/fifos/vtpm-to-%d.fifo"
+ #define VTPM_RX_FIFO "/var/vtpm/fifos/vtpm-from-all.fifo"
+
+ #define BE_LISTENER_THREAD 1
+ #define DMI_LISTENER_THREAD 2
+
+ // Seconds until DMI timeout. Timeouts result in DMI being out
+ // of sync, which may require a reboot of DMI and guest to recover
+ // from. Don't set this to low. Also note that DMI may issue a TPM
+ // call so we should expect time to process at DMI + TPM processing.
+ #define DMI_TIMEOUT 90
+#endif
+
+
+// ------------------------ Private Structures -----------------------
+typedef struct VTPM_DMI_RESOURCE_T {
+ // I/O info for Manager to talk to DMI's over FIFOs
+#ifndef VTPM_MUTLI_VM
+ int guest_tx_fh; // open GUEST_TX_FIFO
+ int vtpm_tx_fh; // open VTPM_TX_FIFO
+ char *guest_tx_fname; // open GUEST_TX_FIFO
+ char *vtpm_tx_fname; // open VTPM_TX_FIFO
+
+ pid_t dmi_pid;
+#endif
+ // Non-persistent Information
+ bool connected;
+ UINT32 dmi_domain_id;
+ TCS_CONTEXT_HANDLE TCSContext; // TCS Handle
+ char *NVMLocation; // NULL term string indicating location
+ // of NVM.
+ // Persistent Information about DMI
+ UINT32 dmi_id;
+ TPM_DIGEST NVM_measurement; // Equal to the SHA1 of the blob
+ TPM_DIGEST DMI_measurement; // Correct measurement of the owning
DMI
+} VTPM_DMI_RESOURCE;
+
+typedef struct tdVTPM_GLOBALS {
+ // Non-persistent data
+ int be_fh; // File handle to ipc used to
communicate with backend
+#ifndef VTPM_MULTI_VM
+ int vtpm_rx_fh;
+ int guest_rx_fh;
+
+ pid_t master_pid;
+#endif
+ struct hashtable *dmi_map; // Table of all DMI's known
indexed by persistent instance #
+#ifndef VTPM_MULTI_VM
+ pthread_mutex_t dmi_map_mutex; //
+#endif
+ TCS_CONTEXT_HANDLE manager_tcs_handle; // TCS Handle used by manager
+ TPM_HANDLE storageKeyHandle; // Key used by persistent store
+ CRYPTO_INFO storageKey; // For software encryption
+ TCS_AUTH keyAuth; // OIAP session for storageKey
+ BOOL DMI_table_dirty; // Indicates that a command
+ // has updated the DMI table
+
+
+ // Persistent Data
+ TPM_AUTHDATA owner_usage_auth; // OwnerAuth of real TPM
+ TPM_AUTHDATA srk_usage_auth; // SRK Auth of real TPM
+ buffer_t storageKeyWrap; // Wrapped copy of storageKey
+
+ TPM_AUTHDATA storage_key_usage_auth;
+
+}VTPM_GLOBALS;
+
+//Global dmi map
+extern VTPM_GLOBALS *vtpm_globals;
+
+// ********************** Command Handler Prototypes ***********************
+TPM_RESULT VTPM_Handle_Load_NVM( VTPM_DMI_RESOURCE *myDMI,
+ const buffer_t *inbuf,
+ buffer_t *outbuf);
+
+TPM_RESULT VTPM_Handle_Save_NVM( VTPM_DMI_RESOURCE *myDMI,
+ const buffer_t *inbuf,
+ buffer_t *outbuf);
+
+TPM_RESULT VTPM_Handle_TPM_Command( VTPM_DMI_RESOURCE *dmi,
+ buffer_t *inbuf,
+ buffer_t *outbuf);
+
+TPM_RESULT VTPM_Handle_New_DMI(const buffer_t *param_buf);
+
+TPM_RESULT VTPM_Handle_Close_DMI(const buffer_t *param_buf);
+
+TPM_RESULT VTPM_Handle_Delete_DMI(const buffer_t *param_buf);
+
+TPM_RESULT VTPM_SaveService(void);
+TPM_RESULT VTPM_LoadService(void);
+
+TPM_RESULT close_dmi( VTPM_DMI_RESOURCE *dmi_res);
+#endif // __VTPMPRIV_H__
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/manager/vtsp.c
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/manager/vtsp.c Thu Sep 1 10:16:14 2005
@@ -0,0 +1,810 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+//
+// vtsp.c
+//
+// Higher level interface to TCS for use in service.
+//
+// ==================================================================
+
+#include <string.h>
+#include "tcg.h"
+#include "tcs.h"
+#include "bsg.h"
+#include "log.h"
+#include "crypto.h"
+#include "vtsp.h"
+#include "buffer.h"
+
+#define RSA_KEY_SIZE 0x0800
+
+/***********************************************************************************
+ * GenerateAuth: Generate authorization info to be sent back to application
+ *
+ * Parameters: outParamDigestText The concatenation of output parameters to
be SHA1ed
+ * outParamDigestTextSize Size of inParamDigestText
+ * HMACkey Key to be used for HMACing
+ * For OIAP use key.authUsage or PersistStore.ownerAuth
+ * For OSAP use shared secret
+ * pAuth Authorization information from the application
+ *
+ * Return: TPM_SUCCESS Authorization data created
+ * TPM_AUTHFAIL Invalid (NULL) HMACkey presented for OSAP
+
*************************************************************************************/
+TPM_RESULT GenerateAuth( /*[IN]*/ const BYTE *inParamDigestText,
+ /*[IN]*/ UINT32 inParamDigestTextSize,
+ /*[IN]*/ const TPM_SECRET *HMACkey,
+ /*[IN,OUT]*/ TCS_AUTH *auth) {
+
+ if (inParamDigestText == NULL || auth == NULL)
+ return (TPM_AUTHFAIL);
+ else {
+
+ //Generate new OddNonce
+ Crypto_GetRandom(auth->NonceOdd.nonce, sizeof(TPM_NONCE));
+
+ // Create SHA1 inParamDigest
+ TPM_DIGEST inParamDigest;
+ Crypto_SHA1Full(inParamDigestText, inParamDigestTextSize, (BYTE *)
&inParamDigest);
+
+ // Create HMAC text. (Concat inParamsDigest with inAuthSetupParams).
+ BYTE hmacText[sizeof(TPM_DIGEST) + (2 * sizeof(TPM_NONCE)) + sizeof(BOOL)];
+
+ BSG_PackList( hmacText, 4,
+ BSG_TPM_DIGEST, &inParamDigest,
+ BSG_TPM_NONCE, &(auth->NonceEven),
+ BSG_TPM_NONCE, &(auth->NonceOdd),
+ BSG_TYPE_BOOL, &(auth->fContinueAuthSession) );
+
+ Crypto_HMAC((BYTE *) hmacText, sizeof(hmacText), (BYTE *) HMACkey,
sizeof(TPM_DIGEST), (BYTE *) &(auth->HMAC));
+
+ return(TPM_SUCCESS);
+
+ }
+}
+
+/***********************************************************************************
+ * VerifyAuth: Verify the authdata for a command requiring authorization
+ *
+ * Parameters: inParamDigestText The concatenation of parameters to be SHA1ed
+ * inParamDigestTextSize Size of inParamDigestText
+ * authDataUsage AuthDataUsage for the Entity being used
+ * Key->authDataUsage or TPM_AUTH_OWNER
+ * HMACkey Key to be used for HMACing
+ * For OIAP use key.authUsage or PersistStore.ownerAuth
+ * For OSAP use NULL (It will be aquired from the Auth Session)
+ * If unknown (default), assume OIAP
+ * sessionAuth A TCS_AUTH info for the session
+ * pAuth Authorization information from the application
+ * hContext If specified, on failed Auth, VerifyAuth will
+ * generate a new OIAP session in place
of themselves
+ * destroyed session.
+ *
+ * Return: TPM_SUCCESS Authorization Verified
+ * TPM_AUTHFAIL Authorization Failed
+ * TPM_FAIL Failure during SHA1 routines
+
*************************************************************************************/
+TPM_RESULT VerifyAuth( /*[IN]*/ const BYTE *outParamDigestText,
+ /*[IN]*/ UINT32 outParamDigestTextSize,
+ /*[IN]*/ const TPM_SECRET *HMACkey,
+ /*[IN,OUT]*/ TCS_AUTH *auth,
+ /*[IN]*/ TCS_CONTEXT_HANDLE hContext) {
+ if (outParamDigestText == NULL || auth == NULL)
+ return (TPM_AUTHFAIL);
+
+
+ // Create SHA1 inParamDigest
+ TPM_DIGEST outParamDigest;
+ Crypto_SHA1Full(outParamDigestText, outParamDigestTextSize, (BYTE *)
&outParamDigest);
+
+ // Create HMAC text. (Concat inParamsDigest with inAuthSetupParams).
+ TPM_DIGEST hm;
+ BYTE hmacText[sizeof(TPM_DIGEST) + (2 * sizeof(TPM_NONCE)) + sizeof(BOOL)];
+
+ BSG_PackList( hmacText, 4,
+ BSG_TPM_DIGEST, &outParamDigest,
+ BSG_TPM_NONCE, &(auth->NonceEven),
+ BSG_TPM_NONCE, &(auth->NonceOdd),
+ BSG_TYPE_BOOL, &(auth->fContinueAuthSession) );
+
+ Crypto_HMAC((BYTE *) hmacText, sizeof(hmacText),
+ (BYTE *) HMACkey, sizeof(TPM_DIGEST), (BYTE *) &hm);
+
+ // Compare correct HMAC with provided one.
+ if (memcmp (&hm, &(auth->HMAC), sizeof(TPM_DIGEST)) == 0) // 0 indicates
equality
+ return (TPM_SUCCESS);
+ else {
+ VTSP_OIAP( hContext, auth);
+ return (TPM_AUTHFAIL);
+ }
+}
+
+TPM_RESULT VTSP_OIAP(const TCS_CONTEXT_HANDLE hContext,
+ TCS_AUTH *auth) {
+
+ vtpmloginfo(VTPM_LOG_VTSP, "OIAP.\n");
+ TPM_RESULT status = TPM_SUCCESS;
+ TPMTRYRETURN( TCSP_OIAP(hContext,
+ &auth->AuthHandle,
+ &auth->NonceEven) );
+ goto egress;
+
+ abort_egress:
+
+ egress:
+
+ return status;
+}
+
+TPM_RESULT VTSP_OSAP(const TCS_CONTEXT_HANDLE hContext,
+ const TPM_ENTITY_TYPE entityType,
+ const UINT32 entityValue,
+ const TPM_AUTHDATA *usageAuth,
+ TPM_SECRET *sharedSecret,
+ TCS_AUTH *auth) {
+
+ vtpmloginfo(VTPM_LOG_VTSP, "OSAP.\n");
+ TPM_RESULT status = TPM_SUCCESS;
+ TPM_NONCE nonceEvenOSAP, nonceOddOSAP;
+
+ Crypto_GetRandom((BYTE *) &nonceOddOSAP, sizeof(TPM_NONCE) );
+
+ TPMTRYRETURN( TCSP_OSAP( hContext,
+ TPM_ET_SRK,
+ 0,
+ nonceOddOSAP,
+ &auth->AuthHandle,
+ &auth->NonceEven,
+ &nonceEvenOSAP) );
+
+ // Calculating Session Secret
+ BYTE sharedSecretText[TPM_DIGEST_SIZE * 2];
+
+ BSG_PackList( sharedSecretText, 2,
+ BSG_TPM_NONCE, &nonceEvenOSAP,
+ BSG_TPM_NONCE, &nonceOddOSAP);
+
+ Crypto_HMAC(sharedSecretText, sizeof(sharedSecretText), (BYTE *) usageAuth,
TPM_DIGEST_SIZE, (BYTE *) sharedSecret);
+
+ goto egress;
+
+ abort_egress:
+
+ egress:
+
+ return status;
+}
+
+
+
+TPM_RESULT VTSP_ReadPubek( const TCS_CONTEXT_HANDLE hContext,
+ CRYPTO_INFO *crypto_info) {
+
+ TPM_RESULT status;
+ TPM_NONCE antiReplay;
+ TPM_DIGEST checksum;
+ BYTE *pubEKtext;
+ UINT32 pubEKtextsize;
+
+ vtpmloginfo(VTPM_LOG_VTSP, "Reading Public EK.\n");
+
+ // GenerateAuth new nonceOdd
+ Crypto_GetRandom(&antiReplay, sizeof(TPM_NONCE) );
+
+
+ TPMTRYRETURN( TCSP_ReadPubek( hContext,
+ antiReplay,
+ &pubEKtextsize,
+ &pubEKtext,
+ &checksum) );
+
+
+ // Extract the remaining output parameters
+ TPM_PUBKEY pubEK;
+
+ BSG_Unpack(BSG_TPM_PUBKEY, pubEKtext, (BYTE *) &pubEK);
+
+ // Build CryptoInfo for the bindingKey
+ TPM_RSA_KEY_PARMS rsaKeyParms;
+
+ BSG_Unpack(BSG_TPM_RSA_KEY_PARMS,
+ pubEK.algorithmParms.parms,
+ &rsaKeyParms);
+
+ Crypto_RSABuildCryptoInfoPublic(rsaKeyParms.exponentSize,
+ rsaKeyParms.exponent,
+ pubEK.pubKey.keyLength,
+ pubEK.pubKey.key,
+ crypto_info);
+
+ // Destroy rsaKeyParms
+ BSG_Destroy(BSG_TPM_RSA_KEY_PARMS, &rsaKeyParms);
+
+ // Set encryption scheme
+ crypto_info->encScheme = CRYPTO_ES_RSAESOAEP_SHA1_MGF1;
+ //crypto_info->encScheme = pubEK.algorithmParms.encScheme;
+ crypto_info->algorithmID = pubEK.algorithmParms.algorithmID;
+
+ goto egress;
+
+ abort_egress:
+
+ egress:
+
+ return status;
+}
+
+TPM_RESULT VTSP_TakeOwnership( const TCS_CONTEXT_HANDLE hContext,
+ const TPM_AUTHDATA *ownerAuth,
+ const TPM_AUTHDATA *srkAuth,
+ CRYPTO_INFO *ek_cryptoInfo,
+ TCS_AUTH *auth) {
+
+ vtpmloginfo(VTPM_LOG_VTSP, "Taking Ownership of TPM.\n");
+
+ TPM_RESULT status = TPM_SUCCESS;
+ TPM_COMMAND_CODE command = TPM_ORD_TakeOwnership;
+ TPM_PROTOCOL_ID proto_id = TPM_PID_OWNER;
+ BYTE *new_srk;
+
+ BYTE *paramText; // Digest to make Auth.
+ UINT32 paramTextSize;
+
+ // vars for srkpubkey parameter
+ TPM_KEY srkPub;
+ TPM_KEY_PARMS srkKeyInfo = {TPM_ALG_RSA, TPM_ES_RSAESOAEP_SHA1_MGF1,
TPM_SS_NONE, 12, 0};
+ BYTE srkRSAkeyInfo[12] = { 0x00, 0x00, (RSA_KEY_SIZE >> 8), 0x00, 0x00,
0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00};
+ srkKeyInfo.parms = (BYTE *) &srkRSAkeyInfo;
+
+ struct pack_buf_t srkText;
+
+ // GenerateAuth new nonceOdd
+ Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) );
+
+ //These values are accurate for an enc(AuthData).
+ struct pack_buf_t encOwnerAuth, encSrkAuth;
+
+ encOwnerAuth.data = (BYTE *)malloc(sizeof(BYTE) * 256);
+ encSrkAuth.data = (BYTE *)malloc(sizeof(BYTE) * 256);
+
+ if (encOwnerAuth.data == NULL || encSrkAuth.data == NULL) {
+ vtpmloginfo(VTPM_LOG_VTSP, "Could not malloc encrypted auths.\n");
+ status = TPM_RESOURCES;
+ goto abort_egress;
+ }
+
+ Crypto_RSAEnc(ek_cryptoInfo, sizeof(TPM_SECRET), (BYTE *) ownerAuth,
&encOwnerAuth.size, encOwnerAuth.data);
+ Crypto_RSAEnc(ek_cryptoInfo, sizeof(TPM_SECRET), (BYTE *) srkAuth,
&encSrkAuth.size, encSrkAuth.data);
+
+
+ // Build srk public key struct
+ srkPub.ver = TPM_STRUCT_VER_1_1;
+ srkPub.keyUsage = TPM_KEY_STORAGE;
+ srkPub.keyFlags = 0x00;
+ srkPub.authDataUsage = TPM_AUTH_ALWAYS;
+ memcpy(&srkPub.algorithmParms, &srkKeyInfo, sizeof(TPM_KEY_PARMS));
+ srkPub.PCRInfoSize = 0;
+ srkPub.PCRInfo = 0;
+ srkPub.pubKey.keyLength= 0;
+ srkPub.encDataSize = 0;
+
+ srkText.data = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
+ srkText.size = BSG_Pack(BSG_TPM_KEY, (BYTE *) &srkPub, srkText.data);
+
+ paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
+
+ paramTextSize = BSG_PackList(paramText, 5,
+ BSG_TPM_COMMAND_CODE,&command,
+ BSG_TPM_PROTOCOL_ID, &proto_id,
+ BSG_TPM_SIZE32_DATA, &encOwnerAuth,
+ BSG_TPM_SIZE32_DATA, &encSrkAuth,
+ BSG_TPM_KEY, &srkPub);
+
+ TPMTRYRETURN( GenerateAuth( paramText, paramTextSize, ownerAuth, auth) );
+
+ new_srk = srkText.data;
+ TPMTRYRETURN( TCSP_TakeOwnership ( hContext,
+ proto_id,
+ encOwnerAuth.size,
+ encOwnerAuth.data,
+ encSrkAuth.size,
+ encSrkAuth.data,
+ &srkText.size,
+ &new_srk,
+ auth ) );
+
+
+ paramTextSize = BSG_PackList(paramText, 2,
+ BSG_TPM_RESULT, &status,
+ BSG_TPM_COMMAND_CODE, &command);
+ memcpy(paramText + paramTextSize, new_srk, srkText.size);
+ paramTextSize += srkText.size;
+
+
+ TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,
+ ownerAuth, auth,
+ hContext) );
+
+ goto egress;
+
+ abort_egress:
+
+ egress:
+
+ free(srkText.data);
+ free(encSrkAuth.data);
+ free(encOwnerAuth.data);
+ free(paramText);
+
+ TCS_FreeMemory(hContext, new_srk);
+
+ return status;
+}
+
+TPM_RESULT VTSP_DisablePubekRead( const TCS_CONTEXT_HANDLE hContext,
+ const TPM_AUTHDATA *ownerAuth,
+ TCS_AUTH *auth) {
+
+ vtpmloginfo(VTPM_LOG_VTSP, "Disabling Pubek Read.\n");
+
+ TPM_RESULT status = TPM_SUCCESS;
+ TPM_COMMAND_CODE command = TPM_ORD_DisablePubekRead;
+
+ BYTE *paramText; // Digest to make Auth.
+ UINT32 paramTextSize;
+
+ // Generate HMAC
+ Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) );
+
+ paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
+
+ paramTextSize = BSG_PackList(paramText, 1,
+ BSG_TPM_COMMAND_CODE, &command);
+
+ TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,
+ ownerAuth, auth) );
+
+ // Call TCS
+ TPMTRYRETURN( TCSP_DisablePubekRead ( hContext, // in
+ auth) );
+
+ // Verify Auth
+ paramTextSize = BSG_PackList(paramText, 2,
+ BSG_TPM_RESULT, &status,
+ BSG_TPM_COMMAND_CODE, &command);
+
+ TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,
+ ownerAuth, auth,
+ hContext) );
+ goto egress;
+
+ abort_egress:
+ egress:
+ free(paramText);
+ return status;
+}
+
+TPM_RESULT VTSP_CreateWrapKey( const TCS_CONTEXT_HANDLE hContext,
+ const TPM_KEY_USAGE usage,
+ const TPM_AUTHDATA *newKeyAuth,
+ const TCS_KEY_HANDLE parentHandle,
+ const TPM_AUTHDATA *osapSharedSecret,
+ buffer_t *pubKeyBuf,
+ TCS_AUTH *auth) {
+
+ int i;
+ TPM_RESULT status = TPM_SUCCESS;
+ TPM_COMMAND_CODE command = TPM_ORD_CreateWrapKey;
+
+ vtpmloginfo(VTPM_LOG_VTSP, "Creating new key of type %d.\n", usage);
+
+ // vars for Calculate encUsageAuth
+ BYTE *paramText;
+ UINT32 paramTextSize;
+
+ // vars for Calculate encUsageAuth
+ BYTE XORbuffer[sizeof(TPM_SECRET) + sizeof(TPM_NONCE)];
+ TPM_DIGEST XORKey1;
+ UINT32 XORbufferSize;
+ TPM_SECRET encUsageAuth, encMigrationAuth;
+
+ // vars for Flatten newKey prototype
+ BYTE *flatKey = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
+ UINT32 flatKeySize = TCPA_MAX_BUFFER_LENGTH;
+ struct pack_buf_t newKeyText;
+
+ // Fill in newKey
+ TPM_KEY newKey;
+
+ BYTE RSAkeyInfo[12] = { 0x00, 0x00, (RSA_KEY_SIZE >> 8), 0x00, 0x00, 0x00,
0x00, 0x02, 0x00, 0x00, 0x00, 0x00};
+ newKey.algorithmParms.algorithmID = TPM_ALG_RSA;
+ newKey.algorithmParms.parms = (BYTE *) &RSAkeyInfo;
+ newKey.algorithmParms.parmSize = 12;
+
+ switch (usage) {
+ case TPM_KEY_SIGNING:
+ vtpmloginfo(VTPM_LOG_VTSP, "Creating Signing Key...\n");
+ newKey.keyUsage = TPM_KEY_SIGNING;
+ newKey.algorithmParms.encScheme = TPM_ES_NONE;
+ newKey.algorithmParms.sigScheme = TPM_SS_RSASSAPKCS1v15_SHA1;
+ break;
+ case TPM_KEY_STORAGE:
+ vtpmloginfo(VTPM_LOG_VTSP, "Creating Storage Key...\n");
+ newKey.keyUsage = TPM_KEY_STORAGE;
+ newKey.algorithmParms.encScheme = TPM_ES_RSAESOAEP_SHA1_MGF1;
+ newKey.algorithmParms.sigScheme = TPM_SS_NONE;
+ break;
+ case TPM_KEY_BIND:
+ vtpmloginfo(VTPM_LOG_VTSP, "Creating Binding Key...\n");
+ newKey.keyUsage = TPM_KEY_BIND;
+ newKey.algorithmParms.encScheme = TPM_ES_RSAESOAEP_SHA1_MGF1;
+ newKey.algorithmParms.sigScheme = TPM_SS_NONE;
+ break;
+ default:
+ vtpmloginfo(VTPM_LOG_VTSP, "Cannot create key. Invalid Key Type.\n");
+ status = TPM_BAD_PARAMETER;
+ goto abort_egress;
+ }
+
+
+ newKey.ver = TPM_STRUCT_VER_1_1;
+
+ newKey.keyFlags = 0;
+ newKey.authDataUsage = TPM_AUTH_ALWAYS;
+ newKey.pubKey.keyLength= 0;
+ newKey.encDataSize = 0;
+ newKey.encData = NULL;
+
+ // FIXME: Support PCR bindings
+ newKey.PCRInfoSize = 0;
+ newKey.PCRInfo = NULL;
+
+ // Calculate encUsageAuth
+ XORbufferSize = BSG_PackList( XORbuffer, 2,
+ BSG_TPM_SECRET, osapSharedSecret,
+ BSG_TPM_NONCE, &auth->NonceEven);
+ Crypto_SHA1Full(XORbuffer, XORbufferSize, (BYTE *) &XORKey1);
+
+ // FIXME: No support for migratable keys.
+ for (i=0; i < TPM_DIGEST_SIZE; i++)
+ ((BYTE *) &encUsageAuth)[i] = ((BYTE *) &XORKey1)[i] ^ ((BYTE *)
newKeyAuth)[i];
+
+ // Flatten newKey prototype
+ flatKeySize = BSG_Pack(BSG_TPM_KEY, (BYTE *) &newKey, flatKey);
+ newKeyText.data = flatKey;
+ newKeyText.size = flatKeySize;
+
+ // GenerateAuth new nonceOdd
+ Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) );
+
+ // Generate HMAC
+ paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
+
+ paramTextSize = BSG_PackList(paramText, 3,
+ BSG_TPM_COMMAND_CODE, &command,
+ BSG_TPM_AUTHDATA, &encUsageAuth,
+ BSG_TPM_AUTHDATA, &encMigrationAuth);
+ memcpy(paramText + paramTextSize, newKeyText.data, newKeyText.size);
+ paramTextSize += newKeyText.size;
+
+
+ TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,
+ osapSharedSecret, auth) );
+
+ // Call TCS
+ TPMTRYRETURN( TCSP_CreateWrapKey( hContext,
+ parentHandle,
+ encUsageAuth,
+ encMigrationAuth,
+ &newKeyText.size,
+ &newKeyText.data,
+ auth) );
+
+ // Verify Auth
+ paramTextSize = BSG_PackList(paramText, 2,
+ BSG_TPM_RESULT, &status,
+ BSG_TPM_COMMAND_CODE, &command);
+ memcpy(paramText + paramTextSize, newKeyText.data, newKeyText.size);
+ paramTextSize += newKeyText.size;
+
+ TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,
+ osapSharedSecret, auth, 0) );
+
+ // Unpack/return key structure
+ TPMTRYRETURN(buffer_init(pubKeyBuf, 0, 0) );
+ TPMTRYRETURN(buffer_append_raw(pubKeyBuf, newKeyText.size, newKeyText.data)
);
+
+ goto egress;
+
+ abort_egress:
+
+ egress:
+
+ free(flatKey);
+ free(paramText);
+ TCS_FreeMemory(hContext, newKeyText.data);
+
+ return status;
+}
+
+TPM_RESULT VTSP_LoadKey(const TCS_CONTEXT_HANDLE hContext,
+ const TCS_KEY_HANDLE hUnwrappingKey,
+ const buffer_t *rgbWrappedKeyBlob,
+ const TPM_AUTHDATA *parentAuth,
+ TPM_HANDLE *newKeyHandle,
+ TCS_AUTH *auth,
+ CRYPTO_INFO *cryptoinfo /*= NULL*/) {
+
+
+ vtpmloginfo(VTPM_LOG_VTSP, "Loading Key.\n%s","");
+
+ TPM_RESULT status = TPM_SUCCESS;
+ TPM_COMMAND_CODE command = TPM_ORD_LoadKey;
+
+ BYTE *paramText; // Digest to make Auth.
+ UINT32 paramTextSize;
+
+ if ((rgbWrappedKeyBlob == NULL) || (parentAuth == NULL) ||
+ (newKeyHandle==NULL) || (auth==NULL)) {
+ status = TPM_BAD_PARAMETER;
+ goto abort_egress;
+ }
+
+ // Generate Extra TCS Parameters
+ TPM_HANDLE phKeyHMAC;
+
+ // Generate HMAC
+ Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) );
+
+ paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
+
+ paramTextSize = BSG_PackList(paramText, 1,
+ BSG_TPM_COMMAND_CODE, &command);
+
+ memcpy(paramText + paramTextSize, rgbWrappedKeyBlob->bytes,
buffer_len(rgbWrappedKeyBlob));
+ paramTextSize += buffer_len(rgbWrappedKeyBlob);
+
+ TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,
+ parentAuth, auth) );
+
+ // Call TCS
+ TPMTRYRETURN( TCSP_LoadKeyByBlob( hContext,
+ hUnwrappingKey,
+ buffer_len(rgbWrappedKeyBlob),
+ rgbWrappedKeyBlob->bytes,
+ auth,
+ newKeyHandle,
+ &phKeyHMAC) );
+
+ // Verify Auth
+ paramTextSize = BSG_PackList(paramText, 3,
+ BSG_TPM_RESULT, &status,
+ BSG_TPM_COMMAND_CODE, &command,
+ BSG_TPM_HANDLE, newKeyHandle);
+
+ TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,
+ parentAuth, auth,
+ hContext) );
+
+ // Unpack/return key structure
+ if (cryptoinfo != NULL) {
+ TPM_KEY newKey;
+
+ BSG_Unpack(BSG_TPM_KEY, rgbWrappedKeyBlob->bytes , &newKey);
+ TPM_RSA_KEY_PARMS rsaKeyParms;
+
+ BSG_Unpack(BSG_TPM_RSA_KEY_PARMS,
+ newKey.algorithmParms.parms,
+ &rsaKeyParms);
+
+ Crypto_RSABuildCryptoInfoPublic(rsaKeyParms.exponentSize,
+ rsaKeyParms.exponent,
+ newKey.pubKey.keyLength,
+ newKey.pubKey.key,
+ cryptoinfo);
+
+ // Destroy rsaKeyParms
+ BSG_Destroy(BSG_TPM_RSA_KEY_PARMS, &rsaKeyParms);
+
+ // Set encryption scheme
+ cryptoinfo->encScheme = CRYPTO_ES_RSAESOAEP_SHA1_MGF1;
+ }
+
+ goto egress;
+
+ abort_egress:
+
+ egress:
+
+ free(paramText);
+ return status;
+}
+
+TPM_RESULT VTSP_Unbind( const TCS_CONTEXT_HANDLE hContext,
+ const TPM_KEY_HANDLE key_handle,
+ const buffer_t *bound_data,
+ const TPM_AUTHDATA *usage_auth,
+ buffer_t *clear_data,
+ TCS_AUTH *auth) {
+
+ vtpmloginfo(VTPM_LOG_VTSP, "Unbinding %d bytes of data.\n",
buffer_len(bound_data));
+
+ TPM_RESULT status = TPM_SUCCESS;
+ TPM_COMMAND_CODE command = TPM_ORD_UnBind;
+
+ BYTE *paramText; // Digest to make Auth.
+ UINT32 paramTextSize;
+
+ // Generate Extra TCS Parameters
+ struct pack_buf_t clear_data32;
+ BYTE *clear_data_text;
+ UINT32 clear_data_size;
+
+ // Generate HMAC
+ Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) );
+
+ struct pack_buf_t bound_data32 = {bound_data->size, bound_data->bytes};
+
+ paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
+
+ paramTextSize = BSG_PackList(paramText, 2,
+ BSG_TPM_COMMAND_CODE, &command,
+ BSG_TPM_SIZE32_DATA, &bound_data32);
+
+ TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,
+ usage_auth, auth) );
+
+ // Call TCS
+ TPMTRYRETURN( TCSP_UnBind( hContext,
+ key_handle,
+ buffer_len(bound_data),
+ bound_data->bytes,
+ auth,
+ &clear_data_size,
+ &clear_data_text) );
+
+
+ // Verify Auth
+ clear_data32.size = clear_data_size;
+ clear_data32.data = clear_data_text;
+ paramTextSize = BSG_PackList(paramText, 3,
+ BSG_TPM_RESULT, &status,
+ BSG_TPM_COMMAND_CODE, &command,
+ BSG_TPM_SIZE32_DATA, &clear_data32);
+
+ TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,
+ usage_auth, auth,
+ hContext) );
+
+ // Unpack/return key structure
+ TPMTRYRETURN(buffer_init(clear_data, 0, 0));
+ TPMTRYRETURN(buffer_append_raw (clear_data, clear_data_size,
clear_data_text) );
+
+ goto egress;
+
+ abort_egress:
+
+ egress:
+
+ free(paramText);
+ TCS_FreeMemory(hContext, clear_data_text);
+
+ return status;
+}
+
+TPM_RESULT VTSP_Bind( CRYPTO_INFO *cryptoInfo,
+ const buffer_t *inData,
+ buffer_t *outData)
+{
+ vtpmloginfo(VTPM_LOG_VTSP, "Binding %d bytes of data.\n",
buffer_len(inData));
+ TPM_BOUND_DATA boundData;
+ UINT32 i;
+
+ // Fill boundData's accessory information
+ boundData.ver = TPM_STRUCT_VER_1_1;
+ boundData.payload = TPM_PT_BIND;
+ boundData.payloadData = inData->bytes;
+
+ // Pack boundData before encryption
+ BYTE* flatBoundData = (BYTE *)malloc(sizeof(BYTE) *
+ (sizeof(TPM_VERSION) +
+ sizeof(TPM_PAYLOAD_TYPE) +
+ buffer_len(inData)));
+ if (flatBoundData == NULL) {
+ return TPM_NOSPACE;
+ }
+ UINT32 flatBoundDataSize = 0;
+ flatBoundDataSize = BSG_PackList( flatBoundData, 2,
+ BSG_TPM_VERSION, &boundData.ver,
+ BSG_TYPE_BYTE, &boundData.payload);
+
+ memcpy(flatBoundData+flatBoundDataSize, inData->bytes, buffer_len(inData));
+ flatBoundDataSize += buffer_len(inData);
+
+ BYTE out_tmp[RSA_KEY_SIZE/8]; // RSAEnc does not do blocking, So this is
what will come out.
+ UINT32 out_tmp_size;
+
+ // Encrypt flatBoundData
+ Crypto_RSAEnc( cryptoInfo,
+ flatBoundDataSize,
+ flatBoundData,
+ &out_tmp_size,
+ out_tmp);
+
+ if (out_tmp_size > RSA_KEY_SIZE/8) {
+ // The result of RSAEnc should be a fixed size based on key size.
+ vtpmlogerror(VTPM_LOG_VTSP, "Enc buffer just overflowed.\n");
+ }
+
+ buffer_init(outData, 0, NULL);
+ buffer_append_raw(outData, out_tmp_size, out_tmp);
+
+ vtpmloginfo(VTPM_LOG_TXDATA, "Bind Generated[%d] = 0x", out_tmp_size);
+ for(i = 0 ; i < out_tmp_size ; i++) {
+ vtpmloginfomore(VTPM_LOG_TXDATA, "%2.2x ", out_tmp[i]);
+ }
+ vtpmloginfomore(VTPM_LOG_TXDATA, "\n");
+
+ // Free flatBoundData
+ free(flatBoundData);
+
+ return TPM_SUCCESS;
+}
+
+// Function Reaches into unsupported TCS command, beware.
+TPM_RESULT VTSP_RawTransmit(const TCS_CONTEXT_HANDLE hContext,
+ const buffer_t *inbuf,
+ buffer_t *outbuf ) {
+
+ vtpmloginfo(VTPM_LOG_VTSP, "Passthrough in use.\n");
+ TPM_RESULT status = TPM_SUCCESS;
+
+ // Generate Extra TCS Parameters
+ BYTE *resultText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
+ UINT32 resultTextSize = TCPA_MAX_BUFFER_LENGTH;
+
+ // Call TCS
+ TPMTRYRETURN( TCSP_RawTransmitData(buffer_len(inbuf), inbuf->bytes,
+ &resultTextSize, resultText) );
+
+ // Unpack/return key structure
+ TPMTRYRETURN(buffer_init (outbuf, resultTextSize, resultText) );
+ goto egress;
+
+ abort_egress:
+
+ egress:
+ TCS_FreeMemory(hContext, resultText);
+ free(resultText);
+ return status;
+}
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/manager/vtsp.h
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/manager/vtsp.h Thu Sep 1 10:16:14 2005
@@ -0,0 +1,102 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+//
+// vtsp.h
+//
+// Higher level interface to TCS.
+//
+// ==================================================================
+
+#ifndef __VTSP_H__
+#define __VTSP_H__
+
+#include "tcg.h"
+#include "tcs.h"
+
+#define KEY_BUFFER_SIZE 2048
+
+TPM_RESULT VTSP_RawTransmit(const TCS_CONTEXT_HANDLE hContext,
+ const buffer_t *inbuf,
+ buffer_t *outbuf );
+
+TPM_RESULT VTSP_OIAP( const TCS_CONTEXT_HANDLE hContext,
+ TCS_AUTH *auth);
+
+TPM_RESULT VTSP_OSAP( const TCS_CONTEXT_HANDLE hContext,
+ const TPM_ENTITY_TYPE entityType,
+ const UINT32 entityValue,
+ const TPM_AUTHDATA *usageAuth,
+ TPM_SECRET *sharedsecret,
+ TCS_AUTH *auth);
+
+TPM_RESULT VTSP_ReadPubek( const TCS_CONTEXT_HANDLE hContext,
+ CRYPTO_INFO *cypto_info);
+
+TPM_RESULT VTSP_TakeOwnership( const TCS_CONTEXT_HANDLE hContext,
+ const TPM_AUTHDATA *ownerAuth,
+ const TPM_AUTHDATA *srkAuth,
+ CRYPTO_INFO *ek_cryptoInfo,
+ TCS_AUTH *auth);
+
+TPM_RESULT VTSP_DisablePubekRead( const TCS_CONTEXT_HANDLE hContext,
+ const TPM_AUTHDATA *ownerAuth,
+ TCS_AUTH *auth);
+
+TPM_RESULT VTSP_CreateWrapKey( const TCS_CONTEXT_HANDLE hContext,
+ const TPM_KEY_USAGE usage,
+ const TPM_AUTHDATA *newKeyAuth,
+ const TCS_KEY_HANDLE parentHandle,
+ const TPM_AUTHDATA *osapSharedSecret,
+ buffer_t *pubKeyBuf,
+ TCS_AUTH *auth);
+
+TPM_RESULT VTSP_LoadKey(const TCS_CONTEXT_HANDLE hContext,
+ const TCS_KEY_HANDLE hUnwrappingKey,
+ const buffer_t *rgbWrappedKeyBlob,
+ const TPM_AUTHDATA *parentAuth,
+ TPM_HANDLE *newKeyHandle,
+ TCS_AUTH *pAuth,
+ CRYPTO_INFO *cryptoinfo);
+
+TPM_RESULT VTSP_Unbind( const TCS_CONTEXT_HANDLE hContext,
+ const TPM_KEY_HANDLE key_handle,
+ const buffer_t *bound_data,
+ const TPM_AUTHDATA *usage_auth,
+ buffer_t *clear_data,
+ TCS_AUTH *auth);
+
+TPM_RESULT VTSP_Bind( CRYPTO_INFO *cryptoInfo,
+ const buffer_t *inData,
+ buffer_t *outData);
+
+#endif //_VTSP_H_
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/tcs/Makefile
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/tcs/Makefile Thu Sep 1 10:16:14 2005
@@ -0,0 +1,18 @@
+XEN_ROOT = ../../..
+include $(XEN_ROOT)/tools/vtpm_manager/Rules.mk
+
+BIN = libTCS.a
+
+all: build
+
+build: $(BIN)
+
+install: build
+
+clean:
+ rm -f *.a *.so *.o *.rpm $(DEP_FILES)
+
+mrproper: clean
+
+$(BIN): $(OBJS)
+ $(AR) rcs $(BIN) $(OBJS)
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/tcs/contextmgr.c
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/tcs/contextmgr.c Thu Sep 1 10:16:14 2005
@@ -0,0 +1,219 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+//
+// contextmgr.c
+//
+// This file contains the context management functions for TCS.
+//
+// ==================================================================
+
+#include <stdio.h>
+#include <string.h>
+#include <malloc.h>
+#include "tcs.h"
+#include "contextmgr.h"
+#include "log.h"
+
+BYTE* AddMemBlock(CONTEXT_HANDLE* pContextHandle, // in
+ int BlockSize) { // in
+
+ BLOCK* pCurrentBlock = NULL;
+ BLOCK* pBlock = NULL;
+
+ // check incoming params
+ if (pContextHandle == NULL || BlockSize == 0)
+ return NULL;
+
+ // Create New Block
+ pBlock = (BLOCK *)malloc(sizeof(BLOCK));
+ if (pBlock == NULL)
+ return (0);
+
+ pBlock->aMemory = (BYTE *)malloc(sizeof(BYTE) * BlockSize);
+ if (pBlock->aMemory == NULL)
+ return (0);
+
+ memset(pBlock->aMemory, 0, BlockSize);
+ pBlock->nBlockSize = BlockSize;
+ pBlock->pNextBlock = NULL;
+
+ // search for the last block created where to add the
+ // newly created block
+ if(pContextHandle->pTopBlock != NULL) {
+ pCurrentBlock = pContextHandle->pTopBlock;
+ while(pCurrentBlock->pNextBlock != NULL)
+ pCurrentBlock = pCurrentBlock->pNextBlock;
+
+
+ pCurrentBlock->pNextBlock= pBlock;
+ } else
+ pContextHandle->pTopBlock = pBlock;
+
+
+ pContextHandle->nBlockCount++;
+
+ return pBlock->aMemory;
+}
+
+
+BOOL DeleteMemBlock(CONTEXT_HANDLE* pContextHandle, // in
+ BYTE* pTCPA_BYTEs) { // in
+ BLOCK* pCurrentBlock = NULL;
+ BLOCK* pParentBlock = NULL;
+ BOOL bFound = FALSE;
+
+ if (pContextHandle == NULL)
+ return FALSE;
+
+
+ // Search for the Block in the context by aMemory pointer
+ pParentBlock = NULL;
+ pCurrentBlock = pContextHandle->pTopBlock;
+
+ while(pCurrentBlock != NULL) {
+ // If aMemory block is found, delete it
+ if(pCurrentBlock->aMemory == pTCPA_BYTEs || pTCPA_BYTEs == NULL) {
+ // if it is the top Block, remove it from the top,
+ // otherwise remove it from the ParentBlock and stitch
+ // the NextBlock to the ParentBlock
+ if(pParentBlock == NULL)
+ pContextHandle->pTopBlock = pContextHandle->pTopBlock->pNextBlock;
+ else
+ pParentBlock->pNextBlock = pCurrentBlock->pNextBlock;
+
+ // delete memory Block associated with pointer pTCPA_BYTEs
+ free(pCurrentBlock->aMemory);
+ pCurrentBlock->aMemory = NULL;
+
+ free(pCurrentBlock);
+ pCurrentBlock = pParentBlock;
+
+ pContextHandle->nBlockCount--;
+ bFound = TRUE;
+ }
+
+ if(pCurrentBlock != NULL) {
+ pParentBlock = pCurrentBlock;
+ pCurrentBlock = pCurrentBlock->pNextBlock;
+ }
+ }
+
+ return bFound;
+}
+
+BOOL AddHandleToList(CONTEXT_HANDLE* pContextHandle, // in
+ TPM_RESOURCE_TYPE type, // in
+ TPM_HANDLE handle) { // in
+ HANDLE_LIST* pNewHandle = NULL;
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Adding Handle to list\n");
+ if (pContextHandle == NULL)
+ return 0;
+
+ pNewHandle = (HANDLE_LIST *)malloc(sizeof(HANDLE_LIST));
+
+ if (pNewHandle == NULL)
+ return (0);
+
+ pNewHandle->handle = handle;
+ pNewHandle->type = type;
+ pNewHandle->pNextHandle = pContextHandle->pHandleList;
+
+ pContextHandle->pHandleList = pNewHandle;
+
+ return 1;
+}
+
+BOOL DeleteHandleFromList( CONTEXT_HANDLE* pContextHandle, // in
+ TPM_HANDLE handle) { // in
+
+ HANDLE_LIST *pCurrentHandle = pContextHandle->pHandleList,
+ *pLastHandle = pCurrentHandle;
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Deleting Handle from list\n");
+
+ if (pContextHandle == NULL)
+ return 0;
+
+ while (1) {
+
+ if (pCurrentHandle->handle == handle) { // Found element
+ if (pCurrentHandle == pLastHandle) { // First element in list
+ pContextHandle->pHandleList = pCurrentHandle->pNextHandle;
+ free(pCurrentHandle);
+ } else { // Ordinary element
+ pLastHandle->pNextHandle = pCurrentHandle->pNextHandle;
+ free(pCurrentHandle);
+ }
+
+ return 1;
+
+ } else { // Not found yet;
+ pLastHandle = pCurrentHandle;
+ pCurrentHandle = pCurrentHandle->pNextHandle;
+ if (pCurrentHandle == NULL) // Found end of list
+ return 0;
+ }
+
+ }
+}
+
+BOOL FreeHandleList( CONTEXT_HANDLE* pContextHandle) { // in
+ HANDLE_LIST* pCurrentHandle;
+ BOOL returncode = TRUE;
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Freeing all handles for context\n");
+
+ if (pContextHandle == NULL)
+ return 1;
+
+ pCurrentHandle = pContextHandle->pHandleList;
+ while (pCurrentHandle != NULL) {
+
+ switch (pCurrentHandle->type) {
+ case TPM_RT_KEY:
+ returncode = returncode && !TCSP_EvictKey((TCS_CONTEXT_HANDLE)
pContextHandle, pCurrentHandle->handle);
+ break;
+ case TPM_RT_AUTH:
+ returncode = returncode && !TCSP_TerminateHandle((TCS_CONTEXT_HANDLE)
pContextHandle, pCurrentHandle->handle);
+ break;
+ default:
+ returncode = FALSE;
+ }
+
+ pCurrentHandle = pCurrentHandle->pNextHandle;
+
+ }
+
+ return 1;
+}
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/tcs/contextmgr.h
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/tcs/contextmgr.h Thu Sep 1 10:16:14 2005
@@ -0,0 +1,81 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+//
+// contextmgr.c
+//
+// This file contains the context management functions for TCS.
+//
+// ==================================================================
+
+#ifndef __CONTEXTMGR_H__
+#define __CONTEXTMGR_H__
+
+#include "tcg.h"
+
+#define BLOCK_SIZE 300
+
+typedef struct block {
+ int nBlockSize;
+ BYTE* aMemory;
+ struct block* pNextBlock;
+} BLOCK;
+
+typedef struct handle_List {
+ TPM_HANDLE handle;
+ TPM_RESOURCE_TYPE type;
+ struct handle_List* pNextHandle;
+} HANDLE_LIST;
+
+typedef struct context_handle {
+ int nBlockCount;
+ BLOCK* pTopBlock;
+ HANDLE_LIST* pHandleList;
+} CONTEXT_HANDLE;
+
+BYTE* AddMemBlock( CONTEXT_HANDLE* pContextHandle, // in
+ int BlockSize); // in
+
+BOOL DeleteMemBlock(CONTEXT_HANDLE* pContextHandle, // in
+ BYTE* pTCPA_BYTEs); // in
+
+
+BOOL AddHandleToList( CONTEXT_HANDLE* pContextHandle, // in
+ TPM_RESOURCE_TYPE type, // in
+ TPM_HANDLE handle); // in
+
+BOOL DeleteHandleFromList( CONTEXT_HANDLE* pContextHandle, // in
+ TPM_HANDLE handle); // in
+
+BOOL FreeHandleList( CONTEXT_HANDLE* pContextHandle); // in
+
+#endif //_CONTEXTMGR_H_
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/tcs/tcs.c
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/tcs/tcs.c Thu Sep 1 10:16:14 2005
@@ -0,0 +1,1102 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+//
+// tcs.c
+//
+// This file contains the functions that implement a TCS.
+//
+// ==================================================================
+
+#include <stdio.h>
+#include <string.h>
+#include <malloc.h>
+
+#include "tcg.h"
+#include "bsg.h"
+#include "tcs.h"
+#include "contextmgr.h"
+#include "tpmddl.h"
+#include "log.h"
+
+// Static Global Vars for the TCS
+static BOOL TCS_m_bConnected;
+static int TCS_m_nCount = 0;
+
+#define TCPA_MAX_BUFFER_LENGTH 0x2000
+
+static BYTE InBuf [TCPA_MAX_BUFFER_LENGTH];
+static BYTE OutBuf[TCPA_MAX_BUFFER_LENGTH];
+
+
+//
---------------------------------------------------------------------------------
+// Initialization/Uninitialization SubComponent API
+//
---------------------------------------------------------------------------------
+TPM_RESULT TCS_create() {
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TPM_RESULT result = TPM_FAIL;
+ TCS_m_bConnected = FALSE;
+
+ if (TCS_m_nCount == 0) {
+ vtpmloginfo(VTPM_LOG_TCS, "Constructing new TCS:\n");
+ hRes = TDDL_Open();
+
+ if (hRes == TDDL_SUCCESS) {
+ TCS_m_bConnected = TRUE;
+ result = TPM_SUCCESS;
+ }
+ } else
+ TCS_m_bConnected = TRUE;
+
+ TCS_m_nCount++;
+
+ return(result);
+}
+
+
+void TCS_destroy()
+{
+ // FIXME: Should iterate through all open contexts and close them.
+ TCS_m_nCount--;
+
+ if (TCS_m_bConnected == TRUE && TCS_m_nCount == 0) {
+ vtpmloginfo(VTPM_LOG_TCS, "Destructing TCS:\n");
+ TDDL_Close();
+ TCS_m_bConnected = FALSE;
+ }
+
+}
+
+TPM_RESULT TCS_Malloc( TCS_CONTEXT_HANDLE hContext, // in
+ UINT32 MemSize, // in
+ BYTE** ppMemPtr) {// out
+
+ TPM_RESULT returnCode = TPM_FAIL;
+ CONTEXT_HANDLE* pContextHandle = (CONTEXT_HANDLE*)hContext;
+
+ if (pContextHandle != NULL && ppMemPtr != NULL) {
+ *ppMemPtr = (BYTE *)AddMemBlock(pContextHandle, MemSize);
+ returnCode = TPM_SUCCESS;
+ }
+
+ return returnCode;
+}
+
+TPM_RESULT TCS_FreeMemory( TCS_CONTEXT_HANDLE hContext, // in
+ BYTE* pMemory) { // in
+ TPM_RESULT returnCode = TPM_FAIL;
+ CONTEXT_HANDLE* pContextHandle = (CONTEXT_HANDLE*)hContext;
+
+ if ( (pContextHandle != NULL && pMemory != NULL) &&
+ (DeleteMemBlock(pContextHandle, pMemory) == TRUE) )
+ returnCode = TPM_SUCCESS;
+
+
+ return returnCode;
+}
+
+TPM_RESULT TCS_OpenContext(TCS_CONTEXT_HANDLE* hContext) { // out
+ TPM_RESULT returnCode = TPM_FAIL;
+
+ vtpmloginfo(VTPM_LOG_TCS, "Calling TCS_OpenContext:\n");
+
+ // hContext must point to a null memory context handle
+ if(*hContext == HANDLE_NULL) {
+ CONTEXT_HANDLE* pContextHandle = (CONTEXT_HANDLE
*)malloc(sizeof(CONTEXT_HANDLE));
+ if (pContextHandle == NULL)
+ return TPM_SIZE;
+
+
+ // initialize to 0
+ pContextHandle->nBlockCount = 0;
+ pContextHandle->pTopBlock = NULL;
+ pContextHandle->pHandleList = NULL;
+
+ // Create New Block
+ AddMemBlock(pContextHandle, BLOCK_SIZE);
+
+ *hContext = (TCS_CONTEXT_HANDLE)pContextHandle;
+ returnCode = TPM_SUCCESS;
+ }
+
+ return(returnCode);
+}
+
+TPM_RESULT TCS_CloseContext(TCS_CONTEXT_HANDLE hContext) {// in
+ //FIXME: TCS SHOULD Track track failed auths and make sure
+ //we don't try and re-free them here.
+ TPM_RESULT returnCode = TPM_FAIL;
+
+ CONTEXT_HANDLE* pContextHandle = (CONTEXT_HANDLE*)hContext;
+
+ if(pContextHandle != NULL) {
+ // Print test info
+ vtpmloginfo(VTPM_LOG_TCS, "Calling TCS_CloseContext.\n");
+
+ // free memory for all the blocks
+ DeleteMemBlock(pContextHandle, NULL );
+ pContextHandle->pTopBlock = NULL;
+
+ FreeHandleList(pContextHandle);
+ if (pContextHandle->pHandleList != NULL)
+ vtpmlogerror(VTPM_LOG_TCS, "Not all handles evicted from TPM.\n");
+
+ // Release the TPM's resources
+ free(pContextHandle);
+ returnCode = TPM_SUCCESS;
+ }
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Finished closing context\n");
+ return(returnCode);
+}
+
+// ------------------------------------------------------------------
+// Internal Functions
+// ------------------------------------------------------------------
+int packAuth(BYTE* dst, TCS_AUTH* auth) {
+ // CHECK: according to the command specs, the outgoing auth params are:
+ // nonceEven
+ // nonceOdd
+ // continueAuthSession
+ // auth digest for return params
+ //
+ // this is a bit different than this code...
+
+ return BSG_PackList(dst, 4,
+ BSG_TYPE_UINT32, &(auth->AuthHandle),
+ BSG_TPM_NONCE, &(auth->NonceOdd),
+ BSG_TYPE_BOOL, &(auth->fContinueAuthSession),
+ BSG_TPM_AUTHDATA, &(auth->HMAC));
+}
+
+int unpackAuth(TCS_AUTH* auth, BYTE* src) {
+ return BSG_UnpackList(src, 3,
+ BSG_TPM_NONCE, &(auth->NonceEven),
+ BSG_TYPE_BOOL, &(auth->fContinueAuthSession),
+ BSG_TPM_AUTHDATA, &(auth->HMAC));
+}
+
+// ------------------------------------------------------------------
+// Authorization Commands
+// ------------------------------------------------------------------
+
+TPM_RESULT TCSP_OIAP(TCS_CONTEXT_HANDLE hContext, // in
+ TCS_AUTHHANDLE* authHandle, // out
+ TPM_NONCE* nonce0) // out
+{
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_COMMAND;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_OIAP;
+ UINT32 paramSize = 0;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // check input params
+ if (authHandle == NULL || nonce0 == NULL)
+ return TPM_BAD_PARAMETER;
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal);
+
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength))
+ == TDDL_SUCCESS) {
+
+ // unpack to get the tag, paramSize, & returnCode
+ int i = BSG_UnpackList( OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &returnCode);
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_COMMAND) {
+ // Extract the remaining output parameters
+ BSG_UnpackList(OutBuf+i, 2,
+ BSG_TYPE_UINT32, authHandle,
+ BSG_TPM_NONCE, nonce0);
+
+ if (!AddHandleToList((CONTEXT_HANDLE *)hContext, TPM_RT_AUTH,
*authHandle))
+ vtpmlogerror(VTPM_LOG_TCS, "New AuthHandle not recorded\n");
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+ } else
+ vtpmlogerror(VTPM_LOG_TCS, "Failed with return code %s\n",
tpm_get_error_name(returnCode));
+
+ }
+
+ return(returnCode);
+}
+
+TPM_RESULT TCSP_OSAP(TCS_CONTEXT_HANDLE hContext, // in
+ TPM_ENTITY_TYPE entityType, // in
+ UINT32 entityValue, // in
+ TPM_NONCE nonceOddOSAP, // in
+ TCS_AUTHHANDLE* authHandle, // out
+ TPM_NONCE* nonceEven, // out
+ TPM_NONCE* nonceEvenOSAP) // out
+{
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_COMMAND;
+ UINT32 paramSize = 0;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_OSAP;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // check input params
+ if (authHandle == NULL || nonceEven == NULL || nonceEvenOSAP == NULL)
+ return TPM_BAD_PARAMETER;
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 6,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal,
+ BSG_TYPE_UINT16, &entityType,
+ BSG_TYPE_UINT32, &entityValue,
+ BSG_TPM_NONCE, &nonceOddOSAP);
+
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength))
+ == TDDL_SUCCESS) {
+
+ // unpack to get the tag, paramSize, & returnCode
+ int i = BSG_UnpackList(OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &returnCode);
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_COMMAND) {
+ // Extract the remaining output parameters
+ BSG_UnpackList(OutBuf+i, 3,
+ BSG_TYPE_UINT32, authHandle,
+ BSG_TPM_NONCE, nonceEven,
+ BSG_TPM_NONCE, nonceEvenOSAP);
+
+ if (!AddHandleToList((CONTEXT_HANDLE *)hContext, TPM_RT_AUTH,
*authHandle)) {
+ vtpmlogerror(VTPM_LOG_TCS, "New AuthHandle not recorded\n");
+ }
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+ } else
+ vtpmlogerror(VTPM_LOG_TCS, "Failed with return code %s\n",
tpm_get_error_name(returnCode));
+
+ }
+
+ return(returnCode);
+}
+
+TPM_RESULT TCSP_TakeOwnership(TCS_CONTEXT_HANDLE hContext, // in
+ UINT16 protocolID, // in
+ UINT32 encOwnerAuthSize, // in
+ BYTE* encOwnerAuth, // in
+ UINT32 encSrkAuthSize, // in
+ BYTE* encSrkAuth, // in
+ UINT32* SrkSize, // in, out
+ BYTE** Srk, // in, out
+ TCS_AUTH* ownerAuth) // in, out
+{
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_AUTH1_COMMAND;
+ UINT32 paramSize = 0;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_TakeOwnership;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // check input params
+ if (encOwnerAuth == NULL || encSrkAuth == NULL || SrkSize == NULL || *Srk ==
NULL)
+ return TPM_BAD_PARAMETER;
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 5,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal,
+ BSG_TYPE_UINT16, &protocolID,
+ BSG_TYPE_UINT32, &encOwnerAuthSize);
+
+ memcpy(InBuf+InLength, encOwnerAuth, encOwnerAuthSize);
+ InLength += encOwnerAuthSize;
+ InLength += BSG_Pack( BSG_TYPE_UINT32,
+ &encSrkAuthSize,
+ InBuf+InLength);
+ memcpy(InBuf+InLength, encSrkAuth, encSrkAuthSize);
+ InLength += encSrkAuthSize;
+ memcpy(InBuf+InLength, *Srk, *SrkSize);
+ InLength += *SrkSize;
+ InLength += packAuth(InBuf+InLength, ownerAuth);
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32,
+ &InLength,
+ InBuf+2);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength))
+ == TDDL_SUCCESS){
+
+ // unpack to get the tag, paramSize, & returnCode
+ int i = BSG_UnpackList( OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &returnCode);
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_AUTH1_COMMAND) {
+ // Extract the remaining output parameters
+ TPM_KEY srkPub;
+ i += BSG_Unpack(BSG_TPM_KEY, OutBuf+i, &srkPub);
+ unpackAuth(ownerAuth, OutBuf+i);
+
+ // fill output params
+ BYTE tempBuf[1024];
+ *SrkSize = BSG_Pack(BSG_TPM_KEY, &srkPub, tempBuf);
+ if (TCS_Malloc(hContext, *SrkSize, Srk) == TPM_FAIL) {
+ return(TPM_SIZE);
+ }
+ memcpy(*Srk, tempBuf, *SrkSize);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d", paramSize);
+ } else
+ vtpmlogerror(VTPM_LOG_TCS, "TCSP_TakeOwnership Failed with return code
%s\n", tpm_get_error_name(returnCode));
+ }
+
+ return(returnCode);
+}
+
+
+TPM_RESULT TCSP_DisablePubekRead ( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_AUTH* ownerAuth) { // in, out
+
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_AUTH1_COMMAND;
+ UINT32 paramSize = 0;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_DisablePubekRead;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal);
+
+ InLength += packAuth(InBuf+InLength, ownerAuth);
+
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength))
+ == TDDL_SUCCESS){
+
+ // unpack to get the tag, paramSize, & returnCode
+ int i = BSG_UnpackList( OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &returnCode);
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_AUTH1_COMMAND) {
+ // Extract the remaining output parameters
+ unpackAuth(ownerAuth, OutBuf+i);
+ } else
+ vtpmlogerror(VTPM_LOG_TCS, "TCSP_DisablePubekRead Failed with return
code %s\n", tpm_get_error_name(returnCode));
+ }
+
+ return(returnCode);
+}
+
+
+TPM_RESULT TCSP_TerminateHandle(TCS_CONTEXT_HANDLE hContext, // in
+ TCS_AUTHHANDLE handle) // in
+{
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_COMMAND;
+ UINT32 paramSize = 0;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_Terminate_Handle;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 4,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal,
+ BSG_TYPE_UINT32, &handle);
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength))
+ == TDDL_SUCCESS) {
+
+ // unpack to get the tag, paramSize, & returnCode
+ BSG_UnpackList(OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &returnCode);
+
+ if (!DeleteHandleFromList((CONTEXT_HANDLE *)hContext, handle))
+ vtpmlogerror(VTPM_LOG_TCS, "KeyHandle not removed from list\n");
+
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_COMMAND) {
+ // Print debug info
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d", paramSize);
+ } else
+ vtpmlogerror(VTPM_LOG_TCS, "TCSP_TerminateHandle Failed with return code
%s\n", tpm_get_error_name(returnCode));
+
+ }
+
+ return(returnCode);
+}
+
+// TPM Mandatory
+TPM_RESULT TCSP_Extend( TCS_CONTEXT_HANDLE hContext, // in
+ TPM_PCRINDEX pcrNum, // in
+ TPM_DIGEST inDigest, // in
+ TPM_PCRVALUE* outDigest) // out
+{
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_COMMAND;
+ UINT32 paramSize = 0;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_Extend;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 5,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal,
+ BSG_TYPE_UINT32, &pcrNum,
+ BSG_TPM_DIGEST, &inDigest);
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength))
+ == TDDL_SUCCESS) {
+
+ // unpack to get the tag, paramSize, & returnCode
+ int i = BSG_UnpackList(OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &returnCode);
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_COMMAND){
+ // Extract the remaining output parameters
+ BSG_Unpack(BSG_TPM_PCRVALUE, OutBuf+i, outDigest);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+ } else
+ vtpmlogerror(VTPM_LOG_TCS, "TCSP_Extend Failed with return code %s\n",
tpm_get_error_name(returnCode));
+ }
+
+ return(returnCode);
+}
+
+TPM_RESULT TCSP_Seal( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE keyHandle, // in
+ TPM_ENCAUTH encAuth, // in
+ UINT32 pcrInfoSize, // in
+ BYTE* PcrInfo, // in
+ UINT32 inDataSize, // in
+ BYTE* inData, // in
+ TCS_AUTH* pubAuth, // in, out
+ UINT32* SealedDataSize, // out
+ BYTE** SealedData) // out
+{
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_AUTH1_COMMAND;
+ UINT32 paramSize = 0;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_Seal;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // check input params
+ if (inData == NULL || pubAuth == NULL || SealedDataSize == NULL ||
*SealedData == NULL)
+ return TPM_BAD_PARAMETER;
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 6,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal,
+ BSG_TYPE_UINT32, &keyHandle,
+ BSG_TPM_ENCAUTH, encAuth,
+ BSG_TYPE_UINT32, &pcrInfoSize);
+ memcpy(InBuf+InLength, PcrInfo, pcrInfoSize);
+ InLength += pcrInfoSize;
+ InLength += BSG_Pack(BSG_TYPE_UINT32, &inDataSize, InBuf+InLength);
+ memcpy(InBuf+InLength, inData, inDataSize);
+ InLength += inDataSize;
+ InLength += packAuth(InBuf+InLength, pubAuth);
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength))
+ == TDDL_SUCCESS) {
+ // unpack OutBuf to get the tag, paramSize, & returnCode
+ int i = BSG_UnpackList(OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &returnCode);
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_AUTH1_COMMAND) {
+ // Extract the remaining output parameters
+ TPM_STORED_DATA sealedData;
+
+ i += BSG_Unpack(BSG_TPM_STORED_DATA, OutBuf+i, &sealedData);
+ unpackAuth(pubAuth, OutBuf+i);
+
+ // fill SealedData
+ BYTE tempBuf[1024];
+ *SealedDataSize = BSG_Pack(BSG_TPM_STORED_DATA, &sealedData, tempBuf);
+ if (TCS_Malloc(hContext, *SealedDataSize, SealedData) == TPM_FAIL) {
+ return TPM_SIZE;
+ }
+ memcpy(*SealedData, tempBuf, *SealedDataSize);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+ } else
+ vtpmlogerror(VTPM_LOG_TCS, "TCSP_Seal Failed with return code %s\n",
tpm_get_error_name(returnCode));
+ }
+
+ return(returnCode);
+}
+
+TPM_RESULT TCSP_Unseal(TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE parentHandle, // in
+ UINT32 SealedDataSize, // in
+ BYTE* SealedData, // in
+ TCS_AUTH* parentAuth, // in, out
+ TCS_AUTH* dataAuth, // in, out
+ UINT32* DataSize, // out
+ BYTE** Data) // out
+{
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_AUTH2_COMMAND;
+ UINT32 paramSize = 0;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_Unseal;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // check input params
+ if (SealedData == NULL || parentAuth == NULL || dataAuth == NULL ||
+ DataSize == NULL || Data == NULL)
+ return TPM_BAD_PARAMETER;
+
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 4,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal,
+ BSG_TYPE_UINT32, &parentHandle);
+ memcpy(InBuf+InLength, SealedData, SealedDataSize);
+ InLength += SealedDataSize;
+ InLength += packAuth(InBuf+InLength, parentAuth);
+ InLength += packAuth(InBuf+InLength, dataAuth);
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) ==
TDDL_SUCCESS) {
+ // unpack OutBuf to get the tag, paramSize, & returnCode
+ int i = BSG_UnpackList( OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &returnCode);
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_AUTH2_COMMAND) {
+ // Extract the remaining output parameters
+ i += BSG_Unpack(BSG_TYPE_UINT32, OutBuf+i, DataSize);
+ if (TCS_Malloc(hContext, *DataSize, Data) == TPM_FAIL) {
+ return TPM_SIZE;
+ }
+ memcpy(*Data, OutBuf+i, *DataSize);
+ i += *DataSize;
+ i += unpackAuth(parentAuth, OutBuf+i);
+ unpackAuth(dataAuth, OutBuf+i);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+ } else
+ vtpmlogerror(VTPM_LOG_TCS, "TCSP_Unseal Failed with return code %s\n",
tpm_get_error_name(returnCode));
+ }
+
+ return(returnCode);
+}
+
+TPM_RESULT TCSP_UnBind(TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE keyHandle, // in
+ UINT32 inDataSize, // in
+ BYTE* inData, // in
+ TCS_AUTH* privAuth, // in, out
+ UINT32* outDataSize, // out
+ BYTE** outData) // out
+{
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_AUTH1_COMMAND;
+ UINT32 paramSize = 0;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_UnBind;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // check input params
+ if (inData == NULL || privAuth == NULL || outDataSize == NULL || *outData ==
NULL)
+ return TPM_BAD_PARAMETER;
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 5,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal,
+ BSG_TYPE_UINT32, &keyHandle,
+ BSG_TYPE_UINT32, &inDataSize);
+ memcpy(InBuf+InLength, inData, inDataSize);
+ InLength += inDataSize;
+ InLength += packAuth(InBuf+InLength, privAuth);
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "\n\tSending paramSize = %d", InLength);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) ==
TDDL_SUCCESS) {
+ // unpack OutBuf to get the tag, paramSize, & returnCode
+ int i = BSG_UnpackList(OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &returnCode);
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_AUTH1_COMMAND) {
+ // Extract the remaining output parameters
+ i += BSG_Unpack(BSG_TYPE_UINT32, OutBuf+i, outDataSize);
+ if (TCS_Malloc(hContext, *outDataSize, outData) == TPM_FAIL)
+ return TPM_SIZE;
+
+ memcpy(*outData, OutBuf+i, *outDataSize);
+ i += *outDataSize;
+ unpackAuth(privAuth, OutBuf+i);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+ } else
+ vtpmlogerror(VTPM_LOG_TCS, "TCSP_UnBind Failed with return code %s\n",
tpm_get_error_name(returnCode));
+ }
+
+ return(returnCode);
+}
+
+TPM_RESULT TCSP_CreateWrapKey(TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE hWrappingKey, // in
+ TPM_ENCAUTH KeyUsageAuth, // in
+ TPM_ENCAUTH KeyMigrationAuth, // in
+ UINT32* pcKeySize, // in, out
+ BYTE** prgbKey, // in, out
+ TCS_AUTH* pAuth) // in, out
+{
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_AUTH1_COMMAND;
+ UINT32 paramSize = 0;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_CreateWrapKey;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // check input params
+ if (pcKeySize == NULL || *prgbKey == NULL || pAuth == NULL)
+ return TPM_BAD_PARAMETER;
+
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 6,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal,
+ BSG_TYPE_UINT32, &hWrappingKey,
+ BSG_TPM_ENCAUTH, KeyUsageAuth,
+ BSG_TPM_ENCAUTH, KeyMigrationAuth);
+ memcpy(InBuf+InLength, *prgbKey, *pcKeySize);
+ InLength += *pcKeySize;
+ InLength += packAuth(InBuf+InLength, pAuth);
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) ==
TDDL_SUCCESS) {
+ // unpack OutBuf to get the tag, paramSize, & returnCode
+ int i = BSG_UnpackList(OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_RESULT, &returnCode);
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_AUTH1_COMMAND) {
+ // Extract the remaining output parameters
+ TPM_KEY wrappedKey;
+
+ i += BSG_Unpack(BSG_TPM_KEY, OutBuf+i, &wrappedKey);
+ unpackAuth(pAuth, OutBuf+i);
+
+ // Fill prgbKey
+ BYTE tempBuf[1024];
+ *pcKeySize = BSG_Pack(BSG_TPM_KEY, &wrappedKey, tempBuf);
+ if (TCS_Malloc(hContext, *pcKeySize, prgbKey) == TPM_FAIL)
+ return TPM_SIZE;
+
+ memcpy(*prgbKey, tempBuf, *pcKeySize);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+ } else
+ vtpmlogerror(VTPM_LOG_TCS, "TCSP_CreateWrapKey Failed with return code
%s\n", tpm_get_error_name(returnCode));
+ }
+
+ return(returnCode);
+}
+
+TPM_RESULT TCSP_LoadKeyByBlob(TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE hUnwrappingKey, // in
+ UINT32 cWrappedKeyBlobSize, // in
+ BYTE* rgbWrappedKeyBlob, // in
+ TCS_AUTH* pAuth, // in, out
+ TCS_KEY_HANDLE* phKeyTCSI, // out
+ TCS_KEY_HANDLE* phKeyHMAC) // out
+{
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_AUTH1_COMMAND;
+ UINT32 paramSize = 0;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_LoadKey;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // check input params
+ if (rgbWrappedKeyBlob == NULL || pAuth == NULL || phKeyTCSI == NULL ||
phKeyHMAC == NULL)
+ return TPM_BAD_PARAMETER;
+
+ *phKeyHMAC = hUnwrappingKey; // the parent key is the one that the TPM use
to make the HMAC calc
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 4,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal,
+ BSG_TYPE_UINT32, &hUnwrappingKey);
+ memcpy(InBuf+InLength, rgbWrappedKeyBlob, cWrappedKeyBlobSize);
+ InLength += cWrappedKeyBlobSize;
+ InLength += packAuth(InBuf+InLength, pAuth);
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) ==
TDDL_SUCCESS) {
+ // unpack OutBuf to get the tag, paramSize, & returnCode
+ int i = BSG_UnpackList(OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &returnCode);
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_AUTH1_COMMAND) {
+ // Extract the remaining output parameters
+ i += BSG_Unpack(BSG_TYPE_UINT32,
+ OutBuf+i,
+ phKeyTCSI);
+ unpackAuth(pAuth, OutBuf+i);
+
+ if (!AddHandleToList((CONTEXT_HANDLE *)hContext, TPM_RT_KEY,
*phKeyTCSI)) {
+ vtpmlogerror(VTPM_LOG_TCS, "New KeyHandle not recorded\n");
+ }
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+ } else
+ vtpmlogerror(VTPM_LOG_TCS, "TCSP_LoadKeyByBlob Failed with return code
%s\n", tpm_get_error_name(returnCode));
+ }
+
+ return(returnCode);
+}
+
+TPM_RESULT TCSP_EvictKey(TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE hKey) // in
+{
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_COMMAND;
+ UINT32 paramSize = 0;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_EvictKey;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 4,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal,
+ BSG_TYPE_UINT32, &hKey);
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) ==
TDDL_SUCCESS) {
+ // unpack OutBuf to get the tag, paramSize, & returnCode
+ BSG_UnpackList(OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &returnCode);
+
+ if (!DeleteHandleFromList((CONTEXT_HANDLE *)hContext, hKey)) {
+ vtpmlogerror(VTPM_LOG_TCS, "KeyHandle not removed from list\n");
+ }
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_COMMAND) {
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+ } else {
+ vtpmlogerror(VTPM_LOG_TCS, "TCSP_EvictKey Failed with return code %s\n",
tpm_get_error_name(returnCode));
+ }
+ }
+
+ return(returnCode);
+}
+
+TPM_RESULT TCSP_GetRandom(TCS_CONTEXT_HANDLE hContext, // in
+ UINT32* bytesRequested, // in, out
+ BYTE** randomBytes) // out
+{
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_COMMAND;
+ UINT32 paramSize = 0;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_GetRandom;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // check input params
+ if (bytesRequested == NULL || *randomBytes == NULL){
+ return TPM_BAD_PARAMETER;
+ }
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 4,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal,
+ BSG_TYPE_UINT32, bytesRequested);
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) ==
TDDL_SUCCESS) {
+ // unpack OutBuf to get the tag, paramSize, & returnCode
+ int i = BSG_UnpackList(OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &returnCode);
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_COMMAND) {
+ // Extract the remaining output parameters
+ BSG_Unpack(BSG_TYPE_UINT32, OutBuf+i, bytesRequested);
+ if (TCS_Malloc(hContext, *bytesRequested, randomBytes) == TPM_FAIL) {
+ return TPM_SIZE;
+ }
+ memcpy(*randomBytes, OutBuf+i+sizeof(UINT32), *bytesRequested);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+ } else {
+ vtpmlogerror(VTPM_LOG_TCS, "TCSP_GetRandom Failed with return code
%s\n", tpm_get_error_name(returnCode));
+ }
+ }
+
+ return(returnCode);
+}
+
+
+TPM_RESULT TCSP_ReadPubek(TCS_CONTEXT_HANDLE hContext, // in
+ TPM_NONCE antiReplay, // in
+ UINT32* pubEndorsementKeySize, // out
+ BYTE** pubEndorsementKey, // out
+ TPM_DIGEST* checksum) // out
+{
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_COMMAND;
+ UINT32 paramSize = 0;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_ReadPubek;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // check input params
+ if (pubEndorsementKeySize == NULL || pubEndorsementKey == NULL || checksum
== NULL) {
+ return TPM_BAD_PARAMETER;
+ }
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 4,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal,
+ BSG_TPM_NONCE, &antiReplay);
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) ==
TDDL_SUCCESS) {
+ // unpack OutBuf to get the tag, paramSize, & returnCode
+ int i = BSG_UnpackList(OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &returnCode);
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_COMMAND) {
+ // Extract the remaining output parameters
+ TPM_PUBKEY pubEK;
+ i += BSG_UnpackList(OutBuf+i, 2,
+ BSG_TPM_PUBKEY, &pubEK,
+ BSG_TPM_DIGEST, checksum);
+
+ // fill EndorsementKey
+ BYTE tempBuf[1024];
+ *pubEndorsementKeySize = BSG_Pack(BSG_TPM_PUBKEY, &pubEK, tempBuf);
+ if (TCS_Malloc(hContext, *pubEndorsementKeySize, pubEndorsementKey) ==
TPM_FAIL) {
+ return TPM_SIZE;
+ }
+ memcpy(*pubEndorsementKey, tempBuf, *pubEndorsementKeySize);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+ } else {
+ vtpmlogerror(VTPM_LOG_TCS, "TCSP_ReadPubek Failed with return code
%s\n", tpm_get_error_name(returnCode));
+ }
+ }
+
+ return(returnCode);
+}
+
+TPM_RESULT TCSP_RawTransmitData( UINT32 inDataSize, // in
+ BYTE *inData, // in
+ UINT32 *outDataSize,// in/out
+ BYTE *outData) { // out
+
+ TDDL_RESULT hRes;
+
+ vtpmloginfo(VTPM_LOG_TCS, "Calling TransmitData directly.\n");
+ //FIXME: Add Context Management
+ hRes = TDDL_TransmitData( inData,
+ inDataSize,
+ outData,
+ outDataSize);
+
+ if (hRes == TDDL_SUCCESS) {
+ return TPM_SUCCESS;
+ } else {
+ vtpmlogerror(VTPM_LOG_TCS, "TCSP_RawTransmitData Failed with return code
%s\n", tpm_get_error_name(TPM_IOERROR));
+ return TPM_IOERROR;
+ }
+
+}
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/tcs/tcs.h
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/tcs/tcs.h Thu Sep 1 10:16:14 2005
@@ -0,0 +1,238 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+//
+// tcs.h
+//
+// This file declares the TCS API
+//
+// ==================================================================
+
+#ifndef __TCS_H__
+#define __TCS_H__
+
+#include "tcg.h"
+#include "buffer.h"
+
+#define HANDLE_NULL 0
+
+// ------------------------------------------------------------------
+// Exposed API
+// ------------------------------------------------------------------
+
+TPM_RESULT TCS_create();
+void TCS_destroy();
+
+TPM_RESULT TCS_OpenContext( /* OUT */ TCS_CONTEXT_HANDLE* hContext );
+
+TPM_RESULT TCS_CloseContext ( /* IN */ TCS_CONTEXT_HANDLE hContext );
+
+TPM_RESULT TCS_Malloc ( TCS_CONTEXT_HANDLE hContext, // in
+ UINT32 MemSize, // in
+ BYTE** ppMemPtr ); //out
+
+TPM_RESULT TCS_FreeMemory ( TCS_CONTEXT_HANDLE hContext, // in
+ BYTE* pMemory); // in
+
+// ------------------------------------------------------------------
+// Exposed API
+// ------------------------------------------------------------------
+
+// TPM v1.1B Command Set
+
+// Authorzation
+TPM_RESULT TCSP_OIAP( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_AUTHHANDLE* authHandle, // out
+ TPM_NONCE* nonce0 // out
+ );
+
+TPM_RESULT TCSP_OSAP ( TCS_CONTEXT_HANDLE hContext, // in
+ TPM_ENTITY_TYPE entityType, // in
+ UINT32 entityValue, // in
+ TPM_NONCE nonceOddOSAP, // in
+ TCS_AUTHHANDLE* authHandle, // out
+ TPM_NONCE* nonceEven, // out
+ TPM_NONCE* nonceEvenOSAP // out
+ );
+
+TPM_RESULT TCSP_TakeOwnership ( TCS_CONTEXT_HANDLE hContext, // in
+ UINT16 protocolID, // in
+ UINT32 encOwnerAuthSize, // in
+ BYTE* encOwnerAuth, // in
+ UINT32 encSrkAuthSize, // in
+ BYTE* encSrkAuth, // in
+ UINT32* SrkSize, // in, out
+ BYTE** Srk, // in, out
+ TCS_AUTH* ownerAuth // in, out
+ );
+
+TPM_RESULT TCSP_DisablePubekRead ( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_AUTH* ownerAuth // in, out
+ );
+
+TPM_RESULT TCSP_TerminateHandle ( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_AUTHHANDLE handle // in
+ );
+
+TPM_RESULT TCSP_FlushSpecific ( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_AUTHHANDLE handle, // in
+ TPM_RESOURCE_TYPE resourceType //in
+ );
+
+// TPM Mandatory
+TPM_RESULT TCSP_Extend ( TCS_CONTEXT_HANDLE hContext, // in
+ TPM_PCRINDEX pcrNum, // in
+ TPM_DIGEST inDigest, // in
+ TPM_PCRVALUE* outDigest // out
+ );
+
+TPM_RESULT TCSP_PcrRead ( TCS_CONTEXT_HANDLE hContext, // in
+ TPM_PCRINDEX pcrNum, // in
+ TPM_PCRVALUE* outDigest // out
+ );
+
+TPM_RESULT TCSP_Quote ( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE keyHandle, // in
+ TPM_NONCE antiReplay, // in
+ UINT32* PcrDataSize, // in, out
+ BYTE** PcrData, // in, out
+ TCS_AUTH* privAuth, // in, out
+ UINT32* sigSize, // out
+ BYTE** sig // out
+ );
+
+TPM_RESULT TCSP_Seal ( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE keyHandle, // in
+ TPM_ENCAUTH encAuth, // in
+ UINT32 pcrInfoSize, // in
+ BYTE* PcrInfo, // in
+ UINT32 inDataSize, // in
+ BYTE* inData, // in
+ TCS_AUTH* pubAuth, // in, out
+ UINT32* SealedDataSize, // out
+ BYTE** SealedData // out
+ );
+
+TPM_RESULT TCSP_Unseal ( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE parentHandle, // in
+ UINT32 SealedDataSize, // in
+ BYTE* SealedData, // in
+ TCS_AUTH* parentAuth, // in, out
+ TCS_AUTH* dataAuth, // in, out
+ UINT32* DataSize, // out
+ BYTE** Data // out
+ );
+
+TPM_RESULT TCSP_DirWriteAuth ( TCS_CONTEXT_HANDLE hContext, // in
+ TPM_DIRINDEX dirIndex, // in
+ TPM_DIRVALUE newContents, // in
+ TCS_AUTH* ownerAuth // in, out
+ );
+
+TPM_RESULT TCSP_DirRead ( TCS_CONTEXT_HANDLE hContext, // in
+ TPM_DIRINDEX dirIndex, // in
+ TPM_DIRVALUE* dirValue // out
+ );
+
+TPM_RESULT TCSP_UnBind ( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE keyHandle, // in
+ UINT32 inDataSize, // in
+ BYTE* inData, // in
+ TCS_AUTH* privAuth, // in, out
+ UINT32* outDataSize, // out
+ BYTE** outData // out
+ );
+
+TPM_RESULT TCSP_CreateWrapKey ( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE hWrappingKey, // in
+ TPM_ENCAUTH KeyUsageAuth, // in
+ TPM_ENCAUTH KeyMigrationAuth, // in
+ UINT32* pcKeySize, // in, out
+ BYTE** prgbKey, // in, out
+ TCS_AUTH* pAuth // in, out
+ );
+
+TPM_RESULT TCSP_LoadKeyByBlob ( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE hUnwrappingKey, // in
+ UINT32 cWrappedKeyBlobSize, // in
+ BYTE* rgbWrappedKeyBlob, // in
+ TCS_AUTH* pAuth, // in, out
+ TCS_KEY_HANDLE* phKeyTCSI, // out
+ TCS_KEY_HANDLE* phKeyHMAC // out
+ );
+
+TPM_RESULT TCSP_GetPubKey ( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE hKey, // in
+ TCS_AUTH* pAuth, // in, out
+ UINT32* pcPubKeySize, // out
+ BYTE** prgbPubKey // out
+ );
+
+TPM_RESULT TCSP_EvictKey ( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE hKey // in
+ );
+
+TPM_RESULT TCSP_Sign ( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE keyHandle, // in
+ UINT32 areaToSignSize, // in
+ BYTE* areaToSign, // in
+ TCS_AUTH* privAuth, // in, out
+ UINT32* sigSize, // out
+ BYTE** sig // out
+ );
+
+TPM_RESULT TCSP_GetRandom ( TCS_CONTEXT_HANDLE hContext, // in
+ UINT32* bytesRequested, // in, out
+ BYTE** randomBytes // out
+ );
+
+TPM_RESULT TCSP_StirRandom ( TCS_CONTEXT_HANDLE hContext, // in
+ UINT32 inDataSize, // in
+ BYTE* inData // in
+ );
+
+TPM_RESULT TCSP_ReadPubek ( TCS_CONTEXT_HANDLE hContext, // in
+ TPM_NONCE antiReplay, // in
+ UINT32* pubEndorsementKeySize, // out
+ BYTE** pubEndorsementKey, // out
+ TPM_DIGEST* checksum // out
+ );
+
+
+// Non-Standard TCSP call to give direct access to TransmitData.
+// Key and Auth Management is done before transfering command to TDDL.
+TPM_RESULT TCSP_RawTransmitData(UINT32 inDataSize, // in
+ BYTE *inData, // in
+ UINT32 *outDataSize,// in/out
+ BYTE *outData); // out
+
+#endif //TCS_H
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/tcs/tpmddl.h
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/tcs/tpmddl.h Thu Sep 1 10:16:14 2005
@@ -0,0 +1,69 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+//
+// tpmddl.c
+//
+// This file defines the TDDLI API
+//
+// ==================================================================
+
+#ifndef __TPMDDL_H__
+#define __TPMDDL_H__
+
+#define TDDL_CAP_PROP_MANUFACTURER 0x0001
+
+#define TDDL_E_FAIL 1
+#define TDDL_E_SUCCESS 0
+#define TDDL_SUCCESS 0
+
+typedef unsigned int TDDL_UINT32;
+typedef TDDL_UINT32 TDDL_RESULT;
+typedef unsigned char TDDL_BYTE;
+
+TDDL_RESULT TDDL_Open();
+void TDDL_Close();
+TDDL_RESULT TDDL_TransmitData( TDDL_BYTE* in,
+ TDDL_UINT32 insize,
+ TDDL_BYTE* out,
+ TDDL_UINT32* outsize);
+TDDL_RESULT TDDL_GetStatus();
+TDDL_RESULT TDDL_GetCapability( TDDL_UINT32 cap,
+ TDDL_UINT32 sub,
+ TDDL_BYTE* buffer,
+ TDDL_UINT32* size);
+TDDL_RESULT TDDL_SetCapability( TDDL_UINT32 cap,
+ TDDL_UINT32 sub,
+ TDDL_BYTE* buffer,
+ TDDL_UINT32* size);
+
+#endif // __TPMDDL_H__
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/tcs/transmit.c
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/tcs/transmit.c Thu Sep 1 10:16:14 2005
@@ -0,0 +1,131 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include "tcg.h"
+#include "buffer.h"
+#include "log.h"
+#include "tpmddl.h"
+
+// flag to track whether TDDL has been opened
+static int g_TDDL_open = 0;
+static int g_fd = -1; // the fd to the TPM
+
+TPM_RESULT
+TDDL_TransmitData( TDDL_BYTE* in,
+ TDDL_UINT32 insize,
+ TDDL_BYTE* out,
+ TDDL_UINT32* outsize) {
+ TPM_RESULT status = TPM_SUCCESS;
+ TDDL_UINT32 i;
+
+ vtpmloginfo(VTPM_LOG_TXDATA, "Sending buffer = 0x");
+ for(i = 0 ; i < insize ; i++)
+ vtpmloginfomore(VTPM_LOG_TXDATA, "%2.2x ", in[i]);
+
+ vtpmloginfomore(VTPM_LOG_TXDATA, "\n");
+
+ ssize_t size = 0;
+ int fd = g_fd;
+
+ // send the request
+ size = write (fd, in, insize);
+ if (size < 0) {
+ vtpmlogerror(VTPM_LOG_TXDATA, "write() failed");
+ ERRORDIE (TPM_IOERROR);
+ }
+ else if ((TDDL_UINT32) size < insize) {
+ vtpmlogerror(VTPM_LOG_TXDATA, "Wrote %d instead of %d bytes!\n", size,
insize);
+ // ... ?
+ }
+
+ // read the response
+ size = read (fd, out, TCPA_MAX_BUFFER_LENGTH);
+ if (size < 0) {
+ vtpmlogerror(VTPM_LOG_TXDATA, "read() failed");
+ ERRORDIE (TPM_IOERROR);
+ }
+
+ vtpmloginfo(VTPM_LOG_TXDATA, "Receiving buffer = 0x");
+ for(i = 0 ; i < size ; i++)
+ vtpmloginfomore(VTPM_LOG_TXDATA, "%2.2x ", out[i]);
+
+ vtpmloginfomore(VTPM_LOG_TXDATA, "\n");
+
+ *outsize = size;
+ // close connection
+ goto egress;
+
+ abort_egress:
+ egress:
+ return status;
+}
+
+TPM_RESULT TDDL_Open() {
+
+ TDDL_RESULT status = TDDL_SUCCESS;
+ int fd = -1;
+
+ if (g_TDDL_open)
+ return TPM_FAIL;
+
+ fd = open ("/dev/tpm0", O_RDWR);
+ if (fd < 0) {
+ vtpmlogerror(VTPM_LOG_TXDATA, "TPM open failed");
+ return TPM_IOERROR;
+ }
+
+ g_fd = fd;
+ g_TDDL_open = 1;
+
+ return status;
+}
+
+void TDDL_Close() {
+ if (! g_TDDL_open)
+ return;
+
+ if (g_fd>= 0) {
+ if (close(g_fd) < 0)
+ vtpmlogerror(VTPM_LOG_TXDATA, "closeing tpm failed");
+
+ g_fd = -1;
+ }
+
+ g_TDDL_open = 0;
+
+}
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/util/Makefile
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/util/Makefile Thu Sep 1 10:16:14 2005
@@ -0,0 +1,18 @@
+XEN_ROOT = ../../..
+include $(XEN_ROOT)/tools/vtpm_manager/Rules.mk
+
+BIN = libTCGUtils.a
+
+all: build
+
+build: $(BIN)
+
+install: build
+
+clean:
+ rm -f *.a *.so *.o *.rpm $(DEP_FILES)
+
+mrproper: clean
+
+$(BIN): $(OBJS)
+ $(AR) rcs $(BIN) $(OBJS)
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/util/bsg.c
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/util/bsg.c Thu Sep 1 10:16:14 2005
@@ -0,0 +1,830 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+//
+// bsg.cpp
+//
+// This file will handle all the TPM Byte Stream functions
+//
+// ==================================================================
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <malloc.h>
+#include "tcg.h"
+#include "crypto.h"
+#include "bsg.h"
+#include "log.h"
+
+static int g_log_recursion_level = 0;
+
+// a largest buffer size. if we get a buf size bigger than this when unpacking,
+// will complain!
+#define BSG_MAX_BUF_SIZE (1<<18)
+
+#define bsglog(fmt, ...) do { \
+ int __i; \
+ for (__i=0; __i < g_log_recursion_level; __i++) { \
+ vtpmloginfomore (VTPM_LOG_BSG, "%s", " "); \
+ } \
+ vtpmloginfomore (VTPM_LOG_BSG, fmt, __VA_ARGS__); \
+ } while (0)
+
+
+// FIXME: trigger the selfcheck--need to use glibc hook to do this
+//BOOL dummy1 = BSG_static_selfcheck();
+
+
+// Interpretting Types
+// -------------------
+//
+// Incoming Types are composed of two parts {format, info} squished into a
+// BSG_UINT32. The first 4 bits is a format spec indicating what type of
+// data it is. If the first 4 bits are zero the info corresponds to a value in
+// BSG_s_fmt[]. This is a structure whose composition is described in
+// BSG_s_fmt[]. If the value is non-zero, info corresponds to the size of the
+// data (in bytes) being passed in. For example a UINT32 being passed in would
+// have a format of (__FMT_CONST | 4). If both, the format and info are zero,
+// this is interpretted as the end of the structure, and the result is
returned.
+
+// these flags are mutually exclusive, so I'll just make them
+// format values which indicate the semantics of the 'info' part and the source
+// data. The above description has been accordingly adjusted.
+
+// format values for determining what type of data the incoming type is
+// it's a 4 bit value, occupying the high 4 bits
+#define __FMT_CONST (1UL << 28) // Constant sized value
+#define __FMT_DATA (2UL << 28) // Believed to be raw data NOT {size,data}
+#define __FMT_SIZE (3UL << 28) // A size. Used in FMT_SIZE??_DATA.
+#define __FMT_HSIZE (4UL << 28) // A number of handles
+#define __FMT_PACKED (5UL << 28) // 'info' is unused; the source data consists
+ // of {size32, data} but we're to pack only
the
+ // data as that is already packed, and so
+ // can/must be unpacked without
+ // explicitly reading it size
+
+#define __FMT_MASK 0x0FFFFFFFUL // this masks out the 4-bit format
+#define __FMT_MASK_SIZE(type) ((type) & __FMT_MASK)
+#define __FMT_MASK_FORMAT(type) ((type) & (~__FMT_MASK))
+
+// constant (8/16/32-bits)
+#define FMT_U8 (__FMT_CONST | 1UL)
+#define FMT_U16 (__FMT_CONST | 2UL)
+#define FMT_U32 (__FMT_CONST | 4UL)
+
+// const with a compiler-computed size
+#define FMT_SIZEOF(type) (__FMT_CONST | sizeof(type))
+
+// other data (size bytes)
+// Used primarily for DIGESTS -> FMT_DATA(20)
+#define FMT_DATA(size) (__FMT_DATA | ((BSG_UINT32) (size) & __FMT_MASK))
+
+// 16/32-bit size followed by N bytes of data
+#define FMT_SIZE16_DATA (__FMT_SIZE | 2UL)
+#define FMT_SIZE32_DATA (__FMT_SIZE | 4UL)
+
+// 16-bit size followed by N key handles
+#define FMT_SIZE16_HANDLES (__FMT_HSIZE | 2UL)
+
+#define DIGEST_SIZE 20
+typedef BSG_UINT32 BSG_HANDLE;
+
+// TCPA_AUTH has 11 fields!
+#define MAX_FIELDS 11
+typedef struct BSG_Format
+{
+ BSG_Type type;
+ const char* name;
+ BSG_UINT32 fields[MAX_FIELDS + 1];
+} BSG_Format;
+
+/*
+ * TCPA structure data formats
+ */
+// this has to be manually kept in sync with the
+// Type enum!! the static_selfcheck() function should be used regularly!
+static BSG_Format s_fmt[] =
+{
+ {BSG_TYPE_UINT32, "BSG_TYPE_UINT32", {FMT_U32, 0}},
+ {BSG_TYPE_UINT16, "BSG_TYPE_UINT16", {FMT_U16, 0}},
+ {BSG_TYPE_BYTE, "BSG_TYPE_BYTE", {FMT_U8, 0}},
+ {BSG_TYPE_BOOL, "BSG_TYPE_BOOL", {FMT_U8, 0}},
+ {BSG_TPM_SIZE32_DATA, "BSG_TPM_SIZE32_DATA", {FMT_SIZE32_DATA, 0}},
+ {BSG_TPM_TAG, "BSG_TPM_TAG", {FMT_SIZEOF(TPM_TAG), 0}},
+ {BSG_TPM_HANDLE, "BSG_TPM_HANDLE", {FMT_SIZEOF(TPM_HANDLE), 0}},
+ {BSG_TPM_RESULT, "BSG_TPM_RESULT", {FMT_SIZEOF(TPM_RESULT), 0}},
+ {BSG_TPM_RESOURCE_TYPE, "BSG_TPM_RESOURCE_TYPE",
{FMT_SIZEOF(TPM_RESOURCE_TYPE), 0}},
+ {BSG_TPM_COMMAND_CODE, "BSG_TPM_COMMAND_CODE", {FMT_U32, 0}},
+ {BSG_TPM_AUTH_DATA_USAGE, "BSG_TPM_AUTH_DATA_USAGE", {FMT_U8, 0}},
+ {BSG_TPM_ALGORITHM_ID, "BSG_TPM_ALGORITHM_ID", {FMT_U32, 0}},
+ {BSG_TPM_PROTOCOL_ID, "BSG_TPM_PROTOCOL_ID", {FMT_SIZEOF(TPM_PROTOCOL_ID),
0}},
+ {BSG_TPM_KEY_USAGE, "BSG_TPM_KEY_USAGE", {FMT_U16, 0}},
+ {BSG_TPM_ENC_SCHEME, "BSG_TPM_ENC_SCHEME", {FMT_U16, 0}},
+ {BSG_TPM_SIG_SCHEME, "BSG_TPM_SIG_SCHEME", {FMT_U16, 0}},
+ {BSG_TPM_MIGRATE_SCHEME, "BSG_TPM_MIGRATE_SCHEME", {FMT_U16, 0}},
+ {BSG_TPM_KEY_FLAGS, "BSG_TPM_KEY_FLAGS", {FMT_U32, 0}},
+
+ {BSG_TPM_AUTHDATA, "BSG_TPM_AUTHDATA", {FMT_DATA(DIGEST_SIZE), 0}},
+ {BSG_TPM_SECRET, "BSG_TPM_SECRET", {BSG_TPM_AUTHDATA, 0}},
+ {BSG_TPM_ENCAUTH, "BSG_TPM_ENCAUTH", {BSG_TPM_AUTHDATA, 0}},
+ {BSG_TPM_PAYLOAD_TYPE, "BSG_TPM_PAYLOAD_TYPE",
{FMT_SIZEOF(TPM_PAYLOAD_TYPE), 0}},
+
+ {BSG_TPM_VERSION, "BSG_TPM_VERSION", {FMT_DATA(4), 0}}, // vers 1.2
+ {BSG_TPM_DIGEST, "BSG_TPM_DIGEST", {FMT_DATA(DIGEST_SIZE), 0}},
+ {BSG_TPM_COMPOSITE_HASH, "BSG_TPM_COMPOSITE_HASH", {BSG_TPM_DIGEST, 0}},
+ {BSG_TPM_CHOSENID_HASH, "BSG_TPM_CHOSENID_HASH", {BSG_TPM_DIGEST, 0}},
+
+ {BSG_TPM_NONCE, "BSG_TPM_NONCE", {FMT_DATA(DIGEST_SIZE), 0}},
+ {BSG_TPM_KEY_HANDLE, "BSG_TPM_KEY_HANDLE", {FMT_SIZEOF(TPM_KEY_HANDLE), 0}},
+ {BSG_TPM_KEY_HANDLE_LIST, "BSG_TPM_KEY_HANDLE_LIST",
+ {FMT_SIZE16_HANDLES, 0}},
+
+ {BSG_TPM_KEY_PARMS, "BSG_TPM_KEY_PARMS", {
+ BSG_TPM_ALGORITHM_ID,
+ BSG_TPM_ENC_SCHEME,
+ BSG_TPM_SIG_SCHEME,
+ FMT_SIZE32_DATA,
+ 0}},
+ {BSG_TPM_RSA_KEY_PARMS, "BSG_TPM_RSA_KEY_PARMS", {
+ FMT_U32, FMT_U32, FMT_SIZE32_DATA, 0}},
+ {BSG_TPM_STORE_PUBKEY, "BSG_TPM_STORE_PUBKEY", {FMT_SIZE32_DATA, 0}},
+ {BSG_TPM_PUBKEY, "BSG_TPM_PUBKEY", {BSG_TPM_KEY_PARMS, BSG_TPM_STORE_PUBKEY,
0}},
+ {BSG_TPM_KEY, "BSG_TPM_KEY", {
+ BSG_TPM_VERSION,
+ BSG_TPM_KEY_USAGE,
+ BSG_TPM_KEY_FLAGS,
+ BSG_TPM_AUTH_DATA_USAGE,
+ BSG_TPM_KEY_PARMS,
+ FMT_SIZE32_DATA, // the PCR_INFO
+ BSG_TPM_STORE_PUBKEY,
+ FMT_SIZE32_DATA, // the encrypted part
+ 0}},
+
+ {BSG_TPM_MIGRATIONKEYAUTH, "BSG_TPM_MIGRATIONKEYAUTH", {
+ BSG_TPM_PUBKEY,
+ BSG_TPM_MIGRATE_SCHEME,
+ BSG_TPM_DIGEST, 0}},
+
+ {BSG_TCPA_AUDIT_EVENT, "TCPA_AUDIT_EVENT", {
+ BSG_TPM_COMMAND_CODE,
+ BSG_TPM_RESULT, 0 }},
+
+ {BSG_TCPA_EVENT_CERT, "TCPA_EVENT_CERT", {
+ BSG_TPM_DIGEST,
+ BSG_TPM_DIGEST,
+ FMT_DATA(2),
+ FMT_SIZE32_DATA, 0}},
+
+ {BSG_TPM_PCR_SELECTION, "BSG_TPM_PCR_SELECTION", {FMT_SIZE16_DATA, 0} },
+ {BSG_TPM_PCR_COMPOSITE, "BSG_TPM_PCR_COMPOSITE", { BSG_TPM_PCR_SELECTION,
+ FMT_SIZE32_DATA,
+ 0} },
+
+ {BSG_TPM_PCR_INFO, "BSG_TPM_PCR_INFO", { BSG_TPM_PCR_SELECTION,
+ BSG_TPM_COMPOSITE_HASH,
+ BSG_TPM_COMPOSITE_HASH,
+ 0} },
+
+
+ {BSG_TPM_STORED_DATA, "BSG_TPM_STORED_DATA", {
+ BSG_TPM_VERSION,
+ FMT_SIZE32_DATA,
+ FMT_SIZE32_DATA,
+ 0}},
+ {BSG_TPM_SYMMETRIC_KEY, "BSG_TPM_SYMMETRIC_KEY", {
+ BSG_TPM_ALGORITHM_ID,
+ BSG_TPM_ENC_SCHEME,
+ FMT_SIZE16_DATA,
+ 0}},
+ {BSG_TPM_STORE_PRIVKEY, "BSG_TPM_STORE_PRIVKEY", {FMT_SIZE32_DATA, 0}},
+ {BSG_TPM_STORE_ASYMKEY, "BSG_TPM_STORE_ASYMKEY", {
+ BSG_TPM_PAYLOAD_TYPE,
+ BSG_TPM_SECRET,
+ BSG_TPM_SECRET,
+ BSG_TPM_DIGEST,
+ BSG_TPM_STORE_PRIVKEY,
+ 0}},
+ {BSG_TPM_MIGRATE_ASYMKEY, "BSG_TPM_MIGRATE_ASYMKEY", {
+ BSG_TPM_PAYLOAD_TYPE,
+ BSG_TPM_SECRET,
+ BSG_TPM_DIGEST,
+ FMT_U32,
+ BSG_TPM_STORE_PRIVKEY,
+ 0}},
+
+ {BSG_TPM_QUOTE_INFO, "BSG_TPM_QUOTE_INFO", {
+ BSG_TPM_VERSION,
+ FMT_DATA(4),
+ BSG_TPM_COMPOSITE_HASH,
+ BSG_TPM_NONCE,
+ 0}},
+
+ {BSG_TPM_IDENTITY_CONTENTS, "BSG_TPM_IDENTITY_CONTENTS", {
+ BSG_TPM_VERSION,
+ FMT_U32,
+ BSG_TPM_CHOSENID_HASH,
+ BSG_TPM_PUBKEY,
+ 0}},
+
+ {BSG_TPM_PCRVALUE, "BSG_TPM_PCRVALUE", {FMT_DATA(DIGEST_SIZE), 0}},
+
+ {BSG_TCPA_PCR_FLAGS, "TCPA_PCR_FLAGS", {
+ FMT_U8,
+ FMT_U8,
+ 0}},
+
+ {BSG_TCS_AUTH, "TCS_AUTH", {
+ BSG_TYPE_UINT32,
+ BSG_TPM_NONCE,
+ BSG_TPM_NONCE,
+ BSG_TYPE_BOOL,
+ BSG_TPM_AUTHDATA,
+ 0}},
+
+ {BSG_TPM_KEY_NONSENSITIVE, "BSG_TPM_KEY_NONSENSITIVE", {
+ BSG_TPM_VERSION,
+ BSG_TPM_KEY_USAGE,
+ BSG_TPM_KEY_FLAGS,
+ BSG_TPM_AUTH_DATA_USAGE,
+ BSG_TPM_KEY_PARMS,
+ FMT_SIZE32_DATA,
+ BSG_TPM_STORE_PUBKEY,
+ 0}},
+
+ {BSG_PACKED, "BSG_PACKED", {
+ __FMT_PACKED,
+ 0 }},
+
+ {BSG_TYPE_MAX, "", {0}},
+};
+
+
+static const BSG_Format* find_format (BSG_Type t) {
+ BSG_Format * f = s_fmt;
+
+ if (t >= BSG_TYPE_MAX) {
+ return NULL;
+ }
+
+ // WARNING: this depends on the enum and s_fmt[] array being in sync! make
+ // sure to run the static_selfcheck() to make sure
+ f = s_fmt + (t - BSG_TYPE_FIRST);
+
+ return f;
+}
+
+//
+// a consistency-checking routine which can be run at compile time
+// (ie. immediately after compilation)
+//
+// tasks:
+// - verify that s_fmt has one entry per Type t, and that entry is at s_fmt[t]
+//
+// conditions:
+// - need that s_fmt[0] is the first type listed in the Type enum! ie the first
+// Type has value 0, not 1
+//
+// FIXME: should have a function be passed in here which is called if the test
+// fails. Then the caller can decide what to do: abort, notify, whatever
+//
+BOOL BSG_static_selfcheck ()
+{
+ int i;
+
+ for (i=BSG_TYPE_FIRST; i <= BSG_TYPE_MAX; i++) {
+ if (s_fmt[i - BSG_TYPE_FIRST].type != i) {
+ bsglog ("%s\n", "BSG: static_selfcheck failed!\n");
+ bsglog ("failure at %i, allegedly %s\n",
+ i, s_fmt[i - BSG_TYPE_FIRST].name);
+ abort();
+ return FALSE;
+ }
+ }
+
+ bsglog ("%s\n", "BSG: static_selfcheck success!");
+ return TRUE;
+}
+
+
+/**
+ * Flatten a TCPA structure into a buffer in big-endian format
+ * @type: TCPA structure type
+ * @src: (IN) TCPA structure (OUT) end of TCPA structure
+ * @dst: (OUT) flattened data
+ * Returns: Flattened size or -1 for unknown types
+ */
+// make it so that it can just run through the whole process and return
+// the packed size, without packing anything. this will be done if dst is NULL.
+static int BSG_Pack_private(BSG_Type type, const BSG_BYTE** src, BSG_BYTE* dst)
+{
+ // check incoming parameters
+ if (*src == NULL)
+ return 0;
+
+ const BSG_BYTE* s = *src;
+ BSG_BYTE* d = dst;
+
+ BSG_UINT32 size = __FMT_MASK_SIZE(type);
+ BSG_UINT32 format = __FMT_MASK_FORMAT(type);
+
+ if (format == __FMT_CONST) // We are dealing with a fixed length value eg.
UINT32
+ {
+ BSG_UINT32 val = 0;
+ switch (size) {
+ case 1: val = * (BYTE*) s; break;
+ case 2: val = * (unsigned short*) s; break;
+ case 4: val = * (BSG_UINT32*) s; break;
+ }
+ if (dst)
+ BSG_PackConst(val, size, d);
+
+ s += size;
+ d += size;
+ } else if (format == __FMT_DATA) { // We are dealing with raw data. Not
sure when
+ // this is used.
+
+ if (dst) {
+ bsglog ("BSG: __FMT_DATA size %d, src %p, dst %p\n", size, s, d);
+ memcpy(d, s, size);
+ }
+
+ s += size;
+ d += size;
+ } else if (format == __FMT_SIZE || format == __FMT_HSIZE) { // It's a size,
followed by that much data or handles
+
+ BSG_UINT32 psize = 0;
+ switch (size) {
+ case 1: psize = * (BYTE*) s; break;
+ case 2: psize = * (unsigned short*) s; break;
+ case 4: psize = * (BSG_UINT32*) s; break;
+ }
+
+ if (dst)
+ BSG_PackConst(psize, size, d);
+
+ s += size;
+ d += size;
+
+ // now 's' points to an address, so cast it to BSG_BYTE**
+ const BSG_BYTE* pdata = * ((BSG_BYTE**) s);
+ s += sizeof(BSG_BYTE*);
+
+ if (format == __FMT_HSIZE) {// This is a list of psize Handles
+ if (dst) {
+ BSG_HANDLE* d2 = (BSG_HANDLE*) d;
+ BSG_HANDLE* p2 = (BSG_HANDLE*) pdata;
+ BSG_UINT32 i;
+ for (i = 0; i < psize; i++)
+ d2[i] = BSG_UnpackConst((BSG_BYTE*)(p2 + i), 4);
+
+ }
+ d += psize * sizeof(BSG_HANDLE);
+ } else {// If it's not psize handles, it's psize data.
+ if (psize > 0) {
+ if (dst) {
+ bsglog ("BSG: __FMT_SIZE, size=%d, src=%p, dst=%p\n",
+ psize, pdata, d);
+ memcpy(d, pdata, psize);
+ }
+ }
+ d += psize;
+ }
+ } else if (format == __FMT_PACKED) {
+ // the source buffer is a pack_constbuf_t, which has a size and a
+ // pointer. just copy the buffer value, the size is not included in the
+ // output stream.
+ pack_constbuf_t * buf = (pack_constbuf_t*) s;
+
+ if (dst) {
+ bsglog ("BSG: __FMT_PACKED, size=%d, src=%p, dst=%p\n",
+ buf->size, buf->data, d);
+ memcpy(d, buf->data, buf->size);
+ }
+
+ s += buf->size;
+ d += buf->size;
+ } else if (format == 0) {// No flags are set. This is a structure & it should
+ // be looked up in the bsg_s_fmt[]
+
+ const BSG_Format* x = find_format (type);
+ if (x == NULL) {
+ vtpmloginfo(VTPM_LOG_BSG, "BSG_Pack: cannot find type %d\n", type);
+ return -1;
+ }
+
+ if (dst)
+ bsglog ("BSG_Pack type %s\n", x->name);
+
+
+ // iterate through the fields
+ const BSG_UINT32* f = x->fields;
+ for (; *f; f++) {
+ int fsize;
+
+ g_log_recursion_level++;
+ fsize = BSG_Pack_private((BSG_Type) *f, &s, dst ? d : NULL);
+ g_log_recursion_level--;
+
+ if (fsize <= 0)
+ return fsize;
+
+ d += fsize;
+ }
+ } else {
+ vtpmlogerror(VTPM_LOG_BSG, "BSG_Pack(): Unknown format %d\n", format);
+ return -1;
+ }
+
+ *src = s;
+ return (d - dst);
+}
+
+/**
+ * Unflatten a TCPA structure from a buffer in big-endian format
+ * @type: TCPA structure type
+ * @src: flattened data
+ * @dst: (IN) TCPA structure (OUT) end of TCPA structure
+ * Returns: Flattened size
+ * Note: Returns flattened size NOT the unpacked structure size
+ */
+static int BSG_Unpack_private(BSG_Type type, const BSG_BYTE* src, BSG_BYTE**
dst) {
+ // check incoming parameters
+ if (src == NULL)
+ return 0;
+
+
+ const BSG_BYTE* s = src;
+ BSG_BYTE* d = dst ? *dst:NULL;
+ if (dst && !d)
+ dst = NULL;
+
+ BSG_UINT32 size = __FMT_MASK_SIZE(type);
+ BSG_UINT32 format = __FMT_MASK_FORMAT(type);
+
+ if (format == __FMT_CONST) {// We are dealing with a fixed length value ie.
UINT32
+
+ BSG_UINT32 val = BSG_UnpackConst(s, size);
+
+ if (dst) {
+ switch (size) {
+ case 1: *(BYTE *) d = (BSG_BYTE) val; break;
+ case 2: *(unsigned short*) d = (unsigned short) val; break;
+ case 4: *(BSG_UINT32*) d = (BSG_UINT32) val; break;
+ }
+ }
+
+ s += size;
+ d += size;
+ } else if (format == __FMT_DATA) {// We are dealing with raw data. Not sure
when this is used.
+ if (dst)
+ memcpy(d, s, size);
+
+ d += size;
+ s += size;
+ } else if (format == __FMT_SIZE || format == __FMT_HSIZE) {// It's a size,
followed by that much data or handles
+
+ BSG_UINT32 psize = BSG_UnpackConst(s, size);
+
+ if (psize > BSG_MAX_BUF_SIZE) {
+ vtpmlogerror(VTPM_LOG_BSG, "BSG_Unpack runs into var-sized data bigger
than %u bytes!!\n",
+ BSG_MAX_BUF_SIZE);
+ return -1;
+ }
+
+ if (dst) {
+ switch (size) {
+ case 1: *(BYTE *) d = (BSG_BYTE) psize; break;
+ case 2: *(unsigned short*) d = (unsigned short) psize; break;
+ case 4: *(BSG_UINT32*) d = (BSG_UINT32) psize; break;
+ }
+ }
+
+ s += size;
+ d += size;
+
+ BSG_BYTE* pdata = NULL;
+
+ if (psize) {
+ if (format == __FMT_HSIZE) { // This is a list of psize Handles
+ if (dst) {
+ BSG_HANDLE* s2 = (BSG_HANDLE*) s;
+ pdata = (BSG_BYTE *)malloc(psize * sizeof(BSG_HANDLE));
+ if (!pdata)
+ return -1;
+
+ BSG_HANDLE* p2 = (BSG_HANDLE*) pdata;
+ BSG_UINT32 i;
+ for (i = 0; i < psize; i++) {
+ BSG_PackConst(s2[i], 4, (BSG_BYTE*)(p2 + i));
+ }
+ }
+ s += psize * sizeof(BSG_HANDLE);
+ } else { // If it's not psize handles, it's psize data.
+ if (dst) {
+ pdata = (BSG_BYTE *)malloc(sizeof(BSG_BYTE) * psize);
+ if (!pdata)
+ return -1;
+ memcpy(pdata, s, psize);
+ }
+ s += psize;
+ }
+ }
+ if (dst)
+ *(void**) d = pdata;
+
+ d += sizeof(void*);
+ } else if (format == __FMT_PACKED) {
+
+ // this doesn't make sense for unpacking!
+ vtpmlogerror(VTPM_LOG_BSG, "BSG_Unpack() called with format __FMT_PACKED. "
+ "This does not make
sense\n");
+
+ return -1;
+ } else if (format == 0) {// No flags are set. This is a structure & it should
+ // be looked up in the bsg_s_fmt[]
+
+ const BSG_Format* x = find_format (type);
+ if (x == NULL) {
+ vtpmlogerror(VTPM_LOG_BSG, "BSG_Unpack: cannot find type %d\n", type);
+ return -1;
+ }
+
+ const BSG_UINT32* f = x->fields;
+ for (; *f; f++) {
+ int fsize = BSG_Unpack_private((BSG_Type) *f, s, dst ? &d:NULL);
+ if (fsize <= 0)
+ return fsize;
+ s += fsize;
+ }
+ }
+
+ if (dst)
+ *dst = d;
+ return (s - src);
+}
+
+/**
+ * Free memory associated with unpacked TCPA structure
+ * @type: TCPA structure type
+ * @src: (IN) TCPA structure (OUT) end of TCPA structure
+ * Note: Destroy should be called on all structures created with Unpack
+ * to ensure that any allocated memory is freed
+ */
+static void BSG_Destroy_private(BSG_Type type, BSG_BYTE** src) {
+ BSG_BYTE* s = *src;
+
+ BSG_UINT32 size = __FMT_MASK_SIZE(type);
+ BSG_UINT32 format = __FMT_MASK_FORMAT(type);
+
+ if ((src == NULL) || (*src == NULL)) {
+ vtpmlogerror(VTPM_LOG_BSG, "BSG_Destroy() called with NULL src\n");
+ return;
+ }
+
+ if (format == __FMT_CONST || format == __FMT_DATA)
+ s += size;
+ else if (format == __FMT_SIZE || format == __FMT_HSIZE) {
+ s += size;
+ BSG_BYTE* ptr = *(BSG_BYTE**) s;
+ if (ptr)
+ free(ptr);
+ s += sizeof(void*);
+ } else if (format == __FMT_PACKED) {
+
+ // this doesn't make sense for unpacking, hence also for Destroy()
+ vtpmlogerror(VTPM_LOG_BSG, "BSG_Destroy() called with format __FMT_PACKED.
"
+ "This does not make
sense\n");
+
+ return;
+ } else if (format == 0) {
+ const BSG_Format* x = find_format (type);
+ if (x == NULL) {
+ vtpmlogerror(VTPM_LOG_BSG, "BSG_Destroy: cannot find type %d\n", type);
+ return;
+ }
+
+ const BSG_UINT32* f = x->fields;
+ for (; *f; f++)
+ BSG_Destroy_private((BSG_Type) *f, &s);
+ }
+
+ *src = s;
+}
+
+int BSG_Pack(BSG_Type type, const void* src, BSG_BYTE* dst)
+{
+ const BSG_BYTE* src2 = (const BSG_BYTE*) src;
+ return BSG_Pack_private(type, &src2, dst);
+}
+
+int BSG_Unpack(BSG_Type type, const BSG_BYTE* src, void* dst)
+{
+ BSG_BYTE* dst2 = (BSG_BYTE*) dst;
+ return BSG_Unpack_private(type, src, dst ? &dst2:NULL);
+}
+
+void BSG_Destroy(BSG_Type type, void* src)
+{
+ BSG_BYTE* src2 = (BSG_BYTE*) src;
+ BSG_Destroy_private(type, &src2);
+}
+
+/**
+ * Pack a 8/16/32-bit constant into a buffer in big-endian format
+ * @val: constant value
+ * @size: constant size in bytes (1, 2, or 4)
+ * @dst: (OUT) buffer
+ */
+void BSG_PackConst(BSG_UINT32 val, int size, BSG_BYTE* dst) {
+ bsglog ("BSG: PackConst on %d of size %i into address %p\n", val, size, dst);
+
+ switch (size) {
+ case 4:
+ dst[0] = (BSG_BYTE)((val >> 24) & 0xff);
+ dst[1] = (BSG_BYTE)((val >> 16) & 0xff);
+ dst[2] = (BSG_BYTE)((val >> 8) & 0xff);
+ dst[3] = (BSG_BYTE)(val & 0xff);
+ break;
+ case 2:
+ dst[0] = (BSG_BYTE)((val >> 8) & 0xff);
+ dst[1] = (BSG_BYTE)(val & 0xff);
+ break;
+ case 1:
+ dst[0] = (BSG_BYTE)(val & 0xff);
+ break;
+ }
+}
+
+/**
+ * Unpack a 8/16/32-bit constant from a buffer in big-endian format
+ * @src: buffer
+ * @size: constant size in bytes (1, 2, or 4)
+ */
+BSG_UINT32 BSG_UnpackConst(const BSG_BYTE* src, int size) {
+ BSG_UINT32 val = 0;
+
+ if (src == NULL)
+ return 0;
+
+ switch (size) {
+ case 4:
+ val = (((BSG_UINT32) src[0]) << 24
+ | ((BSG_UINT32) src[1]) << 16
+ | ((BSG_UINT32) src[2]) << 8
+ | (BSG_UINT32) src[3]);
+ break;
+ case 2:
+ val = (((BSG_UINT32) src[0]) << 8 | (BSG_UINT32) src[1]);
+ break;
+ case 1:
+ val = (BSG_UINT32) src[0];
+ break;
+ }
+ return val;
+}
+
+// Pack a list of parameters. Beware not to send values, but rather you must
+// send a pointer to your values Instead. This includes UINT32's.
+int BSG_PackList( BSG_BYTE* dst, int ParamCount, ... ) {
+ int ParamNumber;
+ BSG_Type format;
+ BSG_BYTE* val = NULL;
+ int size=0;
+
+ va_list paramList;
+ va_start( paramList, ParamCount );
+
+ for( ParamNumber = 1; ParamNumber <= ParamCount; ParamNumber++) {
+ //Strangeness with int is because gcc wanted an int rather than a enum of
ints.
+ format = (BSG_Type) va_arg( paramList, int );
+ val = va_arg( paramList, BSG_BYTE* );
+ size += BSG_Pack(format, val, dst == NULL ? NULL : dst + size);
+ }
+
+ va_end (paramList);
+
+ return size;
+}
+
+// Unpack a list of parameters.
+int BSG_UnpackList( const BSG_BYTE* src, int ParamCount, ... ) {
+ int ParamNumber = 0;
+ BSG_Type format;
+ BSG_BYTE* val = NULL;
+ int size = 0;
+
+ va_list paramList;
+ va_start( paramList, ParamCount );
+
+ for( ParamNumber = 1; ParamNumber <= ParamCount; ParamNumber++) {
+ format = (BSG_Type) va_arg( paramList, int );
+ val = va_arg( paramList, BSG_BYTE* );
+
+ size += BSG_Unpack(format, src + size, val);
+ }
+
+ va_end( paramList );
+
+ return size;
+}
+
+// Destroy any memory allocated by calls to unpack
+void BSG_DestroyList(int ParamCount, ... ) {
+ int ParamNumber = 0;
+ BSG_Type argType;
+ BSG_BYTE* paramValue = NULL;
+
+ va_list paramList;
+ va_start( paramList, ParamCount );
+
+ for( ParamNumber = 1; ParamNumber <= ParamCount; ParamNumber++) {
+ argType = (BSG_Type) va_arg( paramList, int );
+ paramValue = va_arg( paramList, BSG_BYTE* );
+
+ BSG_Destroy(argType, paramValue);
+ }
+
+ va_end( paramList );
+
+ return;
+}
+
+
+// and a tuple version
+TPM_RESULT BSG_DestroyTuple (int numParams, pack_tuple_t params[]) {
+ int i;
+
+ for (i = 0; i < numParams; i++)
+ BSG_Destroy (params[i].type, params[i].addr);
+
+ return TPM_SUCCESS;
+}
+
+
+//
+// wrappers of Pack and PackList which malloc the ouput buffer. to be freed
+// by the caller later
+//
+
+int BSG_PackMalloc (BSG_Type type, const void* src, BSG_BYTE** o_dst) {
+ int size = BSG_Pack (type, src, NULL);
+ BSG_BYTE * dest = (BSG_BYTE*) malloc (size);
+ if (dest == NULL)
+ return -1;
+
+ size = BSG_Pack(type, src, dest);
+ *o_dst = dest;
+ return size;
+}
+
+
+
+int BSG_PackListMalloc(BSG_BYTE** outBuffer, int ParamCount, ... ) {
+ va_list args;
+ int size;
+
+ va_start (args, ParamCount);
+ size = BSG_PackList (NULL, ParamCount, args);
+ va_end (args);
+
+ BSG_BYTE * dest = (BSG_BYTE*) malloc (size);
+ if (dest == NULL)
+ return -1;
+
+ va_start (args, ParamCount);
+ size = BSG_PackList (dest, ParamCount, args);
+ va_end (args);
+
+ *outBuffer = dest;
+ return size;
+}
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/util/bsg.h
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/util/bsg.h Thu Sep 1 10:16:14 2005
@@ -0,0 +1,166 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+//
+// bsg.h
+//
+// This file contains API's for the TPM Byte Stream functions
+//
+// ==================================================================
+
+#ifndef __BSG_H__
+#define __BSG_H__
+
+#include <stdarg.h>
+#include "buffer.h"
+
+typedef unsigned int BSG_UINT32;
+typedef unsigned char BSG_BYTE;
+
+// forward decl
+struct pack_const_tuple_t;
+
+struct pack_tuple_t;
+
+
+/**
+ * Byte stream generator
+ */
+// this has to be manually kept in sync with the
+// s_fmt array!!
+// but now we have a self-check function which can make sure things are well
+// (if used!)
+typedef enum BSG_Type
+{
+ BSG_TYPE_FIRST = 1,
+ BSG_TYPE_UINT32 = 1, // start at 1 so that Type 0 only serves as an
+ // unused/special value
+ BSG_TYPE_UINT16,
+ BSG_TYPE_BYTE,
+ BSG_TYPE_BOOL,
+ BSG_TPM_SIZE32_DATA, // a 32 bit unsigned size, followed by
+ // a pointer to that much data. can pass a
+ // struct pack_buf_t as the param
+ BSG_TPM_TAG,
+ BSG_TPM_HANDLE,
+ BSG_TPM_RESULT,
+ BSG_TPM_RESOURCE_TYPE,
+ BSG_TPM_COMMAND_CODE,
+ BSG_TPM_AUTH_DATA_USAGE,
+ BSG_TPM_ALGORITHM_ID,
+ BSG_TPM_PROTOCOL_ID,
+ BSG_TPM_KEY_USAGE,
+ BSG_TPM_ENC_SCHEME,
+ BSG_TPM_SIG_SCHEME,
+ BSG_TPM_MIGRATE_SCHEME,
+ BSG_TPM_KEY_FLAGS,
+ BSG_TPM_AUTHDATA,
+ BSG_TPM_SECRET,
+ BSG_TPM_ENCAUTH,
+ BSG_TPM_PAYLOAD_TYPE,
+
+ BSG_TPM_VERSION,
+ BSG_TPM_DIGEST,
+ BSG_TPM_COMPOSITE_HASH,
+ BSG_TPM_CHOSENID_HASH,
+ BSG_TPM_NONCE,
+ BSG_TPM_KEY_HANDLE,
+ BSG_TPM_KEY_HANDLE_LIST,
+ BSG_TPM_KEY_PARMS,
+ BSG_TPM_RSA_KEY_PARMS,
+ BSG_TPM_STORE_PUBKEY,
+ BSG_TPM_PUBKEY,
+ BSG_TPM_KEY,
+
+ BSG_TPM_MIGRATIONKEYAUTH,
+ BSG_TCPA_AUDIT_EVENT,
+ BSG_TCPA_EVENT_CERT,
+ BSG_TPM_PCR_SELECTION,
+ BSG_TPM_PCR_COMPOSITE,
+ BSG_TPM_PCR_INFO,
+ BSG_TPM_STORED_DATA,
+ BSG_TPM_SYMMETRIC_KEY,
+ BSG_TPM_STORE_PRIVKEY,
+ BSG_TPM_STORE_ASYMKEY,
+ BSG_TPM_MIGRATE_ASYMKEY,
+ BSG_TPM_QUOTE_INFO,
+ BSG_TPM_IDENTITY_CONTENTS,
+ BSG_TPM_PCRVALUE,
+ BSG_TCPA_PCR_FLAGS,
+ BSG_TCS_AUTH,
+
+ // this is the BSG_TPM_KEY struct without the encData field
+ BSG_TPM_KEY_NONSENSITIVE,
+
+ BSG_PACKED,
+
+ BSG_TYPE_MAX
+} BSG_Type;
+
+struct pack_const_tuple_t {
+ BSG_Type type;
+ const void * addr;
+};
+
+
+typedef struct pack_tuple_t {
+ BSG_Type type;
+ void * addr;
+} pack_tuple_t;
+
+int BSG_Pack(BSG_Type type, const void* src, BSG_BYTE* dst);
+int BSG_Unpack(BSG_Type type, const BSG_BYTE* src, void* dst);
+void BSG_Destroy(BSG_Type type, void* src);
+
+// wrappers of Pack and PackList which malloc the ouput buffer. to be freed
+// by the caller later. returns size of allocated buffer, or -1 in case
+// allocation failed
+int BSG_PackMalloc (BSG_Type type, const void* src, BSG_BYTE** o_dst);
+int BSG_PackListMalloc (BSG_BYTE** outBuffer, int ParamCount, ... );
+
+// a va_list version of PackList
+int BSG_PackList(BSG_BYTE* outBuffer, int ParamCount, ... );
+int BSG_UnpackList(const BSG_BYTE* inBuffer, int ParamCount, ... );
+void BSG_DestroyList(int ParamCount, ... );
+
+// wrapper of PackList which uses a buffer_t
+TPM_RESULT BSG_PackListBuf (buffer_t * o_buf, int ParamCount, ...);
+
+// and a tuple version
+TPM_RESULT BSG_DestroyTuple (int numParams, pack_tuple_t params[]);
+
+void BSG_PackConst(BSG_UINT32 val, int size, BSG_BYTE* dst);
+BSG_UINT32 BSG_UnpackConst(const BSG_BYTE* src, int size);
+
+BOOL BSG_static_selfcheck ();
+
+#endif
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/util/buffer.c
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/util/buffer.c Thu Sep 1 10:16:14 2005
@@ -0,0 +1,213 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+
+
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/param.h>
+
+#include "tcg.h"
+#include "bsg.h"
+#include "buffer.h"
+
+static TPM_RESULT buffer_priv_realloc (buffer_t * buf, tpm_size_t newsize);
+
+//
+// buffer functions!
+//
+
+TPM_RESULT buffer_init (buffer_t * buf, tpm_size_t initsize, const BYTE*
initval) {
+ if (initsize == 0) {
+ memset(buf, 0, sizeof(*buf));
+ return TPM_SUCCESS;
+ }
+
+
+ buf->bytes = (BYTE*) malloc (initsize);
+ if (buf->bytes == NULL)
+ return TPM_RESOURCES;
+
+ buf->size = initsize;
+ buf->alloc_size = initsize;
+
+ if (initval)
+ memcpy (buf->bytes, initval, initsize);
+
+ buf->is_owner = TRUE;
+
+ return TPM_SUCCESS;
+}
+
+TPM_RESULT buffer_init_convert (buffer_t * buf, tpm_size_t initsize, BYTE*
initval) {
+
+ buf->size = initsize;
+ buf->alloc_size = initsize;
+ buf->bytes = initval;
+
+ buf->is_owner = TRUE;
+
+ return TPM_SUCCESS;
+}
+
+TPM_RESULT buffer_init_copy (buffer_t * buf, const buffer_t * src) {
+ TPM_RESULT status = buffer_init (buf, src->size, src->bytes);
+ buf->is_owner = TRUE;
+
+ return status;
+}
+
+
+
+// make an alias to a constant array
+TPM_RESULT buffer_init_const (buffer_t * buf, tpm_size_t size, const BYTE*
val) {
+ // TODO: try to enforce the const things somehow!
+ buf->bytes = (BYTE*) val;
+ buf->size = size;
+ buf->alloc_size = 0; // this field is now unneeded
+
+ buf->is_owner = FALSE;
+
+ return TPM_SUCCESS;
+}
+
+// make an alias into buf, with given offset and length
+// if len = 0, make the alias go to the end of buf
+TPM_RESULT buffer_init_alias (buffer_t * buf, const buffer_t * b,
+ tpm_size_t offset, tpm_size_t len) {
+ if (offset + len > b->size) {
+ return TPM_NOSPACE;
+ }
+
+ buf->bytes = b->bytes + offset;
+ buf->size = len > 0 ? len : b->size - offset;
+
+ //VS/ buf->alloc_size = 0;
+ if (len ==0)
+ buf->alloc_size = b->alloc_size - offset;
+ else
+ buf->alloc_size = MIN(b->alloc_size - offset, len);
+
+
+ buf->is_owner = FALSE;
+
+ return TPM_SUCCESS;
+}
+
+
+// copy into the start of dest
+TPM_RESULT buffer_copy (buffer_t * dest, const buffer_t* src)
+{
+ TPM_RESULT status = TPM_SUCCESS;
+
+ if (dest->alloc_size < src->size) {
+ status = buffer_priv_realloc (dest, src->size);
+ STATUSCHECK (status);
+ }
+
+ memcpy (dest->bytes, src->bytes, src->size);
+ dest->size = src->size;
+
+ //VS/ dest->is_owner = TRUE;
+
+ abort_egress:
+
+ return status;
+}
+
+
+
+BOOL buffer_eq (const buffer_t * a, const buffer_t * b) {
+ return (a->size == b->size && memcmp (a->bytes, b->bytes, a->size) == 0);
+}
+
+
+void buffer_memset (buffer_t * buf, BYTE b) {
+ memset (buf->bytes, b, buf->size);
+}
+
+
+TPM_RESULT buffer_append_raw (buffer_t * buf, tpm_size_t len, const BYTE*
bytes) {
+ TPM_RESULT status = TPM_SUCCESS;
+
+ if (buf->alloc_size < buf->size + len) {
+ status = buffer_priv_realloc (buf, buf->size + len);
+ STATUSCHECK (status);
+ }
+
+ memcpy (buf->bytes + buf->size, bytes, len);
+
+ buf->size += len;
+
+ goto egress;
+
+ abort_egress:
+
+ egress:
+
+ return status;
+}
+
+tpm_size_t buffer_len (const buffer_t* buf) {
+ return buf->size;
+}
+
+TPM_RESULT buffer_free (buffer_t * buf) {
+ if (buf && buf->is_owner && buf->bytes != NULL) {
+ free (buf->bytes);
+ buf->bytes = NULL;
+ }
+
+ return TPM_SUCCESS;
+}
+
+TPM_RESULT buffer_priv_realloc (buffer_t * buf, tpm_size_t newsize) {
+
+ // we want to realloc to twice the size, or the new size, whichever
+ // bigger
+
+ BYTE * tmpbuf = NULL;
+
+ newsize = MAX (buf->alloc_size * 2, newsize);
+
+ tmpbuf = (BYTE*) realloc (buf->bytes, newsize);
+ if (tmpbuf == NULL)
+ return TPM_SIZE;
+
+
+ buf->bytes = tmpbuf;
+ buf->alloc_size = newsize;
+
+ return TPM_SUCCESS;
+}
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/util/buffer.h
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/util/buffer.h Thu Sep 1 10:16:14 2005
@@ -0,0 +1,103 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+
+#ifndef __VTPM_BUFFER_H__
+#define __VTPM_BUFFER_H__
+
+#include <stddef.h> // for pointer NULL
+#include "tcg.h"
+
+// structure to enable use of FMT_SIZE32_DATA in BSG_Unpack
+typedef struct pack_buf_t {
+ UINT32 size;
+ BYTE * data;
+} pack_buf_t;
+
+// and a const version for Pack
+typedef struct pack_constbuf_t {
+ UINT32 size;
+ const BYTE* data;
+} pack_constbuf_t;
+
+typedef UINT32 tpm_size_t;
+
+// first version, probably will be expanded...
+
+#define NULL_BUF {0,0,0,0}
+
+typedef struct {
+ // private!!
+ tpm_size_t size, alloc_size;
+ BYTE * bytes;
+
+ BOOL is_owner; // do we own this buffer, and need to free it?
+} buffer_t;
+
+// allocate the buffer if initsize > 0, copying over initval if provided
+TPM_RESULT buffer_init (buffer_t * buf,
+ tpm_size_t initsize,
+ const BYTE* initval);
+
+// Create a new buffer from a BYTE *. Use buffer_free to destroy original BYTE
*
+TPM_RESULT buffer_init_convert (buffer_t * buf,
+ tpm_size_t initsize,
+ BYTE* initval);
+
+// make an alias to a constant array, no copying
+TPM_RESULT buffer_init_const (buffer_t * buf, tpm_size_t size, const BYTE*
val);
+
+// make an alias into buf, with given offset and length
+// if len = 0, make the alias go to the end of buf
+TPM_RESULT buffer_init_alias (buffer_t * buf, const buffer_t * b,
+ tpm_size_t offset, tpm_size_t);
+
+// "copy constructor"
+TPM_RESULT buffer_init_copy (buffer_t * buf, const buffer_t * src);
+
+
+// copy into the start of a
+TPM_RESULT buffer_copy (buffer_t * dest, const buffer_t* src);
+
+// are they equal?
+BOOL buffer_eq (const buffer_t * a, const buffer_t * b);
+
+// set the buffer to a constant byte
+void buffer_memset (buffer_t * buf, BYTE b);
+
+tpm_size_t buffer_len (const buffer_t* buf);
+
+TPM_RESULT buffer_free (buffer_t * buf);
+
+TPM_RESULT buffer_append_raw (buffer_t * buf, tpm_size_t len, const BYTE*
bytes);
+
+#endif // _TOOLS_H_
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/util/depend
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/util/depend Thu Sep 1 10:16:14 2005
@@ -0,0 +1,7 @@
+hashtable.o: hashtable.c hashtable.h hashtable_private.h
+hashtable_itr.o: hashtable_itr.c hashtable.h hashtable_private.h \
+ hashtable_itr.h
+bsg.o: bsg.c tcg.h ../crypto/crypto.h ../crypto/sym_crypto.h buffer.h \
+ bsg.h log.h
+log.o: log.c buffer.h tcg.h
+buffer.o: buffer.c tcg.h bsg.h buffer.h
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/util/hashtable.c
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/util/hashtable.c Thu Sep 1 10:16:14 2005
@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) 2005, Intel Corp
+ * Copyright (c) 2002, Christopher Clark <firstname.lastname@xxxxxxxxxxxx>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "hashtable.h"
+#include "hashtable_private.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+/*
+Credit for primes table: Aaron Krowne
+ http://br.endernet.org/~akrowne/
+ http://planetmath.org/encyclopedia/GoodHashTablePrimes.html
+*/
+static const unsigned int primes[] = {
+53, 97, 193, 389,
+769, 1543, 3079, 6151,
+12289, 24593, 49157, 98317,
+196613, 393241, 786433, 1572869,
+3145739, 6291469, 12582917, 25165843,
+50331653, 100663319, 201326611, 402653189,
+805306457, 1610612741
+};
+const unsigned int prime_table_length = sizeof(primes)/sizeof(primes[0]);
+const float max_load_factor = 0.65;
+
+/*****************************************************************************/
+struct hashtable *
+create_hashtable(unsigned int minsize,
+ unsigned int (*hashf) (void*),
+ int (*eqf) (void*,void*))
+{
+ struct hashtable *h;
+ unsigned int pindex, size = primes[0];
+ /* Check requested hashtable isn't too large */
+ if (minsize > (1u << 30)) return NULL;
+ /* Enforce size as prime */
+ for (pindex=0; pindex < prime_table_length; pindex++) {
+ if (primes[pindex] > minsize) { size = primes[pindex]; break; }
+ }
+ h = (struct hashtable *)malloc(sizeof(struct hashtable));
+ if (NULL == h) return NULL; /*oom*/
+ h->table = (struct entry **)malloc(sizeof(struct entry*) * size);
+ if (NULL == h->table) { free(h); return NULL; } /*oom*/
+ memset(h->table, 0, size * sizeof(struct entry *));
+ h->tablelength = size;
+ h->primeindex = pindex;
+ h->entrycount = 0;
+ h->hashfn = hashf;
+ h->eqfn = eqf;
+ h->loadlimit = (unsigned int) ceil(size * max_load_factor);
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_init(&h->mutex, NULL);
+#endif
+ return h;
+}
+
+/*****************************************************************************/
+unsigned int
+hash(struct hashtable *h, void *k)
+{
+ unsigned int i = h->hashfn(k);
+ i += ~(i << 9);
+ i ^= ((i >> 14) | (i << 18)); /* >>> */
+ i += (i << 4);
+ i ^= ((i >> 10) | (i << 22)); /* >>> */
+ return i;
+}
+
+/*****************************************************************************/
+static int
+hashtable_expand(struct hashtable *h)
+{
+ /* Double the size of the table to accomodate more entries */
+ struct entry **newtable;
+ struct entry *e;
+ struct entry **pE;
+ unsigned int newsize, i, index;
+ /* Check we're not hitting max capacity */
+ if (h->primeindex == (prime_table_length - 1)) return 0;
+ newsize = primes[++(h->primeindex)];
+
+ newtable = (struct entry **)malloc(sizeof(struct entry*) * newsize);
+ if (NULL != newtable)
+ {
+ memset(newtable, 0, newsize * sizeof(struct entry *));
+ /* This algorithm is not 'stable'. ie. it reverses the list
+ * when it transfers entries between the tables */
+ for (i = 0; i < h->tablelength; i++) {
+ while (NULL != (e = h->table[i])) {
+ h->table[i] = e->next;
+ index = indexFor(newsize,e->h);
+ e->next = newtable[index];
+ newtable[index] = e;
+ }
+ }
+ free(h->table);
+ h->table = newtable;
+ }
+ /* Plan B: realloc instead */
+ else
+ {
+ newtable = (struct entry **)
+ realloc(h->table, newsize * sizeof(struct entry *));
+ if (NULL == newtable) { (h->primeindex)--; return 0; }
+ h->table = newtable;
+ memset(newtable[h->tablelength], 0, newsize - h->tablelength);
+ for (i = 0; i < h->tablelength; i++) {
+ for (pE = &(newtable[i]), e = *pE; e != NULL; e = *pE) {
+ index = indexFor(newsize,e->h);
+ if (index == i)
+ {
+ pE = &(e->next);
+ }
+ else
+ {
+ *pE = e->next;
+ e->next = newtable[index];
+ newtable[index] = e;
+ }
+ }
+ }
+ }
+ h->tablelength = newsize;
+ h->loadlimit = (unsigned int) ceil(newsize * max_load_factor);
+ return -1;
+}
+
+/*****************************************************************************/
+unsigned int
+hashtable_count(struct hashtable *h)
+{
+ unsigned int count;
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_lock(&h->mutex);
+#endif
+ count = h->entrycount;
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_unlock(&h->mutex);
+#endif
+ return count;
+}
+
+/*****************************************************************************/
+int
+hashtable_insert(struct hashtable *h, void *k, void *v)
+{
+ /* This method allows duplicate keys - but they shouldn't be used */
+ unsigned int index;
+ struct entry *e;
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_lock(&h->mutex);
+#endif
+ if (++(h->entrycount) > h->loadlimit)
+ {
+ /* Ignore the return value. If expand fails, we should
+ * still try cramming just this value into the existing table
+ * -- we may not have memory for a larger table, but one more
+ * element may be ok. Next time we insert, we'll try expanding again.*/
+ hashtable_expand(h);
+ }
+ e = (struct entry *)malloc(sizeof(struct entry));
+ if (NULL == e) { --(h->entrycount); return 0; } /*oom*/
+ e->h = hash(h,k);
+ index = indexFor(h->tablelength,e->h);
+ e->k = k;
+ e->v = v;
+ e->next = h->table[index];
+ h->table[index] = e;
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_unlock(&h->mutex);
+#endif
+ return -1;
+}
+
+/*****************************************************************************/
+void * /* returns value associated with key */
+hashtable_search(struct hashtable *h, void *k)
+{
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_lock(&h->mutex);
+#endif
+ struct entry *e;
+ unsigned int hashvalue, index;
+ hashvalue = hash(h,k);
+ index = indexFor(h->tablelength,hashvalue);
+ e = h->table[index];
+ while (NULL != e)
+ {
+ /* Check hash value to short circuit heavier comparison */
+ if ((hashvalue == e->h) && (h->eqfn(k, e->k))) {
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_unlock(&h->mutex);
+#endif
+ return e->v;
+ }
+ e = e->next;
+ }
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_unlock(&h->mutex);
+#endif
+ return NULL;
+}
+
+/*****************************************************************************/
+void * /* returns value associated with key */
+hashtable_remove(struct hashtable *h, void *k)
+{
+ /* TODO: consider compacting the table when the load factor drops enough,
+ * or provide a 'compact' method. */
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_lock(&h->mutex);
+#endif
+ struct entry *e;
+ struct entry **pE;
+ void *v;
+ unsigned int hashvalue, index;
+
+ hashvalue = hash(h,k);
+ index = indexFor(h->tablelength,hash(h,k));
+ pE = &(h->table[index]);
+ e = *pE;
+ while (NULL != e)
+ {
+ /* Check hash value to short circuit heavier comparison */
+ if ((hashvalue == e->h) && (h->eqfn(k, e->k)))
+ {
+ *pE = e->next;
+ h->entrycount--;
+ v = e->v;
+ freekey(e->k);
+ free(e);
+ return v;
+ }
+ pE = &(e->next);
+ e = e->next;
+ }
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_unlock(&h->mutex);
+#endif
+ return NULL;
+}
+
+/*****************************************************************************/
+/* destroy */
+void
+hashtable_destroy(struct hashtable *h, int free_values)
+{
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_lock(&h->mutex);
+#endif
+ unsigned int i;
+ struct entry *e, *f;
+ struct entry **table = h->table;
+ if (free_values)
+ {
+ for (i = 0; i < h->tablelength; i++)
+ {
+ e = table[i];
+ while (NULL != e)
+ { f = e; e = e->next; freekey(f->k); free(f->v); free(f); }
+ }
+ }
+ else
+ {
+ for (i = 0; i < h->tablelength; i++)
+ {
+ e = table[i];
+ while (NULL != e)
+ { f = e; e = e->next; freekey(f->k); free(f); }
+ }
+ }
+ free(h->table);
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_destroy(&h->mutex);
+#endif
+ free(h);
+}
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/util/hashtable.h
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/util/hashtable.h Thu Sep 1 10:16:14 2005
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2005, Intel Corp
+ * Copyright (c) 2002, Christopher Clark <firstname.lastname@xxxxxxxxxxxx>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef __HASHTABLE_CWC22_H__
+#define __HASHTABLE_CWC22_H__
+
+struct hashtable;
+
+/* Example of use:
+ *
+ * struct hashtable *h;
+ * struct some_key *k;
+ * struct some_value *v;
+ *
+ * static unsigned int hash_from_key_fn( void *k );
+ * static int keys_equal_fn ( void *key1, void *key2 );
+ *
+ * h = create_hashtable(16, hash_from_key_fn, keys_equal_fn);
+ * k = (struct some_key *) malloc(sizeof(struct some_key));
+ * v = (struct some_value *) malloc(sizeof(struct some_value));
+ *
+ * (initialise k and v to suitable values)
+ *
+ * if (! hashtable_insert(h,k,v) )
+ * { exit(-1); }
+ *
+ * if (NULL == (found = hashtable_search(h,k) ))
+ * { printf("not found!"); }
+ *
+ * if (NULL == (found = hashtable_remove(h,k) ))
+ * { printf("Not found\n"); }
+ *
+ */
+
+/* Macros may be used to define type-safe(r) hashtable access functions, with
+ * methods specialized to take known key and value types as parameters.
+ *
+ * Example:
+ *
+ * Insert this at the start of your file:
+ *
+ * DEFINE_HASHTABLE_INSERT(insert_some, struct some_key, struct some_value);
+ * DEFINE_HASHTABLE_SEARCH(search_some, struct some_key, struct some_value);
+ * DEFINE_HASHTABLE_REMOVE(remove_some, struct some_key, struct some_value);
+ *
+ * This defines the functions 'insert_some', 'search_some' and 'remove_some'.
+ * These operate just like hashtable_insert etc., with the same parameters,
+ * but their function signatures have 'struct some_key *' rather than
+ * 'void *', and hence can generate compile time errors if your program is
+ * supplying incorrect data as a key (and similarly for value).
+ *
+ * Note that the hash and key equality functions passed to create_hashtable
+ * still take 'void *' parameters instead of 'some key *'. This shouldn't be
+ * a difficult issue as they're only defined and passed once, and the other
+ * functions will ensure that only valid keys are supplied to them.
+ *
+ * The cost for this checking is increased code size and runtime overhead
+ * - if performance is important, it may be worth switching back to the
+ * unsafe methods once your program has been debugged with the safe methods.
+ * This just requires switching to some simple alternative defines - eg:
+ * #define insert_some hashtable_insert
+ *
+ */
+
+/*****************************************************************************
+ * create_hashtable
+
+ * @name create_hashtable
+ * @param minsize minimum initial size of hashtable
+ * @param hashfunction function for hashing keys
+ * @param key_eq_fn function for determining key equality
+ * @return newly created hashtable or NULL on failure
+ */
+
+struct hashtable *
+create_hashtable(unsigned int minsize,
+ unsigned int (*hashfunction) (void*),
+ int (*key_eq_fn) (void*,void*));
+
+/*****************************************************************************
+ * hashtable_insert
+
+ * @name hashtable_insert
+ * @param h the hashtable to insert into
+ * @param k the key - hashtable claims ownership and will free on removal
+ * @param v the value - does not claim ownership
+ * @return non-zero for successful insertion
+ *
+ * This function will cause the table to expand if the insertion would take
+ * the ratio of entries to table size over the maximum load factor.
+ *
+ * This function does not check for repeated insertions with a duplicate key.
+ * The value returned when using a duplicate key is undefined -- when
+ * the hashtable changes size, the order of retrieval of duplicate key
+ * entries is reversed.
+ * If in doubt, remove before insert.
+ */
+
+int
+hashtable_insert(struct hashtable *h, void *k, void *v);
+
+#define DEFINE_HASHTABLE_INSERT(fnname, keytype, valuetype) \
+int fnname (struct hashtable *h, keytype *k, valuetype *v) \
+{ \
+ return hashtable_insert(h,k,v); \
+}
+
+/*****************************************************************************
+ * hashtable_search
+
+ * @name hashtable_search
+ * @param h the hashtable to search
+ * @param k the key to search for - does not claim ownership
+ * @return the value associated with the key, or NULL if none found
+ */
+
+void *
+hashtable_search(struct hashtable *h, void *k);
+
+#define DEFINE_HASHTABLE_SEARCH(fnname, keytype, valuetype) \
+valuetype * fnname (struct hashtable *h, keytype *k) \
+{ \
+ return (valuetype *) (hashtable_search(h,k)); \
+}
+
+/*****************************************************************************
+ * hashtable_remove
+
+ * @name hashtable_remove
+ * @param h the hashtable to remove the item from
+ * @param k the key to search for - does not claim ownership
+ * @return the value associated with the key, or NULL if none found
+ */
+
+void * /* returns value */
+hashtable_remove(struct hashtable *h, void *k);
+
+#define DEFINE_HASHTABLE_REMOVE(fnname, keytype, valuetype) \
+valuetype * fnname (struct hashtable *h, keytype *k) \
+{ \
+ return (valuetype *) (hashtable_remove(h,k)); \
+}
+
+
+/*****************************************************************************
+ * hashtable_count
+
+ * @name hashtable_count
+ * @param h the hashtable
+ * @return the number of items stored in the hashtable
+ */
+unsigned int
+hashtable_count(struct hashtable *h);
+
+
+/*****************************************************************************
+ * hashtable_destroy
+
+ * @name hashtable_destroy
+ * @param h the hashtable
+ * @param free_values whether to call 'free' on the remaining values
+ */
+
+void
+hashtable_destroy(struct hashtable *h, int free_values);
+
+#endif /* __HASHTABLE_CWC22_H__ */
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/util/hashtable_itr.c
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/util/hashtable_itr.c Thu Sep 1 10:16:14 2005
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2005, Intel Corp
+ * Copyright (c) 2002, Christopher Clark <firstname.lastname@xxxxxxxxxxxx>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "hashtable.h"
+#include "hashtable_private.h"
+#include "hashtable_itr.h"
+#include <stdlib.h> /* defines NULL */
+
+/*****************************************************************************/
+/* hashtable_iterator - iterator constructor */
+
+struct hashtable_itr *
+hashtable_iterator(struct hashtable *h)
+{
+ unsigned int i, tablelength;
+ struct hashtable_itr *itr = (struct hashtable_itr *)
+ malloc(sizeof(struct hashtable_itr));
+ if (NULL == itr) return NULL;
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_lock(&h->mutex);
+#endif
+ itr->h = h;
+ itr->e = NULL;
+ itr->parent = NULL;
+ tablelength = h->tablelength;
+ itr->index = tablelength;
+ if (0 == h->entrycount) {
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_unlock(&h->mutex);
+#endif
+ return itr;
+ }
+
+ for (i = 0; i < tablelength; i++)
+ {
+ if (NULL != h->table[i])
+ {
+ itr->e = h->table[i];
+ itr->index = i;
+ break;
+ }
+ }
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_unlock(&h->mutex);
+#endif
+ return itr;
+}
+
+/*****************************************************************************/
+/* key - return the key of the (key,value) pair at the current position */
+/* value - return the value of the (key,value) pair at the current position
*/
+
+void *
+hashtable_iterator_key(struct hashtable_itr *i)
+{ return i->e->k; }
+
+void *
+hashtable_iterator_value(struct hashtable_itr *i)
+{ return i->e->v; }
+
+/*****************************************************************************/
+/* advance - advance the iterator to the next element
+ * returns zero if advanced to end of table */
+
+int
+hashtable_iterator_advance(struct hashtable_itr *itr)
+{
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_lock(&itr->h->mutex);
+#endif
+ unsigned int j,tablelength;
+ struct entry **table;
+ struct entry *next;
+ int ret;
+ if (NULL == itr->e) { /* stupidity check */
+ ret = 0;
+ goto egress;
+ }
+
+ next = itr->e->next;
+ if (NULL != next)
+ {
+ itr->parent = itr->e;
+ itr->e = next;
+ ret = -1;
+ goto egress;
+ }
+
+ tablelength = itr->h->tablelength;
+ itr->parent = NULL;
+ if (tablelength <= (j = ++(itr->index)))
+ {
+ itr->e = NULL;
+ ret = 0;
+ goto egress;
+ }
+ table = itr->h->table;
+ while (NULL == (next = table[j]))
+ {
+ if (++j >= tablelength)
+ {
+ itr->index = tablelength;
+ itr->e = NULL;
+ ret = 0;
+ goto egress;
+ }
+ }
+ itr->index = j;
+ itr->e = next;
+ ret = -1;
+
+ egress:
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_unlock(&itr->h->mutex);
+#endif
+ return ret;
+}
+
+/*****************************************************************************/
+/* remove - remove the entry at the current iterator position
+ * and advance the iterator, if there is a successive
+ * element.
+ * If you want the value, read it before you remove:
+ * beware memory leaks if you don't.
+ * Returns zero if end of iteration. */
+
+int
+hashtable_iterator_remove(struct hashtable_itr *itr)
+{
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_lock(&itr->h->mutex);
+#endif
+ struct entry *remember_e, *remember_parent;
+ int ret;
+
+ /* Do the removal */
+ if (NULL == (itr->parent))
+ {
+ /* element is head of a chain */
+ itr->h->table[itr->index] = itr->e->next;
+ } else {
+ /* element is mid-chain */
+ itr->parent->next = itr->e->next;
+ }
+ /* itr->e is now outside the hashtable */
+ remember_e = itr->e;
+ itr->h->entrycount--;
+ freekey(remember_e->k);
+
+ /* Advance the iterator, correcting the parent */
+ remember_parent = itr->parent;
+ ret = hashtable_iterator_advance(itr);
+ if (itr->parent == remember_e) { itr->parent = remember_parent; }
+ free(remember_e);
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_unlock(&itr->h->mutex);
+#endif
+ return ret;
+}
+
+/*****************************************************************************/
+int /* returns zero if not found */
+hashtable_iterator_search(struct hashtable_itr *itr,
+ struct hashtable *h, void *k)
+{
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_lock(&h->mutex);
+#endif
+ struct entry *e, *parent;
+ unsigned int hashvalue, index;
+ int ret;
+
+ hashvalue = hash(h,k);
+ index = indexFor(h->tablelength,hashvalue);
+
+ e = h->table[index];
+ parent = NULL;
+ while (NULL != e)
+ {
+ /* Check hash value to short circuit heavier comparison */
+ if ((hashvalue == e->h) && (h->eqfn(k, e->k)))
+ {
+ itr->index = index;
+ itr->e = e;
+ itr->parent = parent;
+ itr->h = h;
+ ret= -1;
+ goto egress;
+ }
+ parent = e;
+ e = e->next;
+ }
+ ret = 0;
+
+egress:
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_lock(&h->mutex);
+#endif
+ return ret;
+}
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/util/hashtable_itr.h
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/util/hashtable_itr.h Thu Sep 1 10:16:14 2005
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2005, Intel Corp
+ * Copyright (c) 2002, Christopher Clark <firstname.lastname@xxxxxxxxxxxx>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef __HASHTABLE_ITR_CWC22__
+#define __HASHTABLE_ITR_CWC22__
+#include "hashtable.h"
+#include "hashtable_private.h" /* needed to enable inlining */
+
+/*****************************************************************************/
+/* This struct is only concrete here to allow the inlining of two of the
+ * accessor functions. */
+struct hashtable_itr
+{
+ struct hashtable *h;
+ struct entry *e;
+ struct entry *parent;
+ unsigned int index;
+};
+
+
+/*****************************************************************************/
+/* hashtable_iterator
+ */
+
+struct hashtable_itr *
+hashtable_iterator(struct hashtable *h);
+
+/*****************************************************************************/
+/* hashtable_iterator_key
+ * - return the value of the (key,value) pair at the current position */
+
+void *hashtable_iterator_key(struct hashtable_itr *i);
+
+/*****************************************************************************/
+/* value - return the value of the (key,value) pair at the current position */
+
+void *hashtable_iterator_value(struct hashtable_itr *i);
+
+/*****************************************************************************/
+/* advance - advance the iterator to the next element
+ * returns zero if advanced to end of table */
+
+int
+hashtable_iterator_advance(struct hashtable_itr *itr);
+
+/*****************************************************************************/
+/* remove - remove current element and advance the iterator to the next element
+ * NB: if you need the value to free it, read it before
+ * removing. ie: beware memory leaks!
+ * returns zero if advanced to end of table */
+
+int
+hashtable_iterator_remove(struct hashtable_itr *itr);
+
+/*****************************************************************************/
+/* search - overwrite the supplied iterator, to point to the entry
+ * matching the supplied key.
+ h points to the hashtable to be searched.
+ * returns zero if not found. */
+int
+hashtable_iterator_search(struct hashtable_itr *itr,
+ struct hashtable *h, void *k);
+
+#define DEFINE_HASHTABLE_ITERATOR_SEARCH(fnname, keytype) \
+int fnname (struct hashtable_itr *i, struct hashtable *h, keytype *k) \
+{ \
+ return (hashtable_iterator_search(i,h,k)); \
+}
+
+
+
+#endif /* __HASHTABLE_ITR_CWC22__*/
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/util/hashtable_private.h
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/util/hashtable_private.h Thu Sep 1 10:16:14 2005
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2005, Intel Corp
+ * Copyright (c) 2002, Christopher Clark <firstname.lastname@xxxxxxxxxxxx>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HASHTABLE_PRIVATE_CWC22_H__
+#define __HASHTABLE_PRIVATE_CWC22_H__
+
+#include "hashtable.h"
+#ifdef HASHTABLE_THREADED
+#include <pthread.h>
+#endif
+
+/*****************************************************************************/
+struct entry
+{
+ void *k, *v;
+ unsigned int h;
+ struct entry *next;
+};
+
+struct hashtable {
+ unsigned int tablelength;
+ struct entry **table;
+ unsigned int entrycount;
+ unsigned int loadlimit;
+ unsigned int primeindex;
+ unsigned int (*hashfn) (void *k);
+ int (*eqfn) (void *k1, void *k2);
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_t mutex;
+#endif
+};
+
+/*****************************************************************************/
+unsigned int
+hash(struct hashtable *h, void *k);
+
+/*****************************************************************************/
+/* indexFor */
+static inline unsigned int
+indexFor(unsigned int tablelength, unsigned int hashvalue) {
+ return (hashvalue % tablelength);
+};
+
+/* Only works if tablelength == 2^N */
+/*static inline unsigned int
+indexFor(unsigned int tablelength, unsigned int hashvalue)
+{
+ return (hashvalue & (tablelength - 1u));
+}
+*/
+
+/*****************************************************************************/
+#define freekey(X) free(X)
+/*define freekey(X) ; */
+
+
+/*****************************************************************************/
+
+#endif /* __HASHTABLE_PRIVATE_CWC22_H__*/
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/util/log.c
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/util/log.c Thu Sep 1 10:16:14 2005
@@ -0,0 +1,142 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "buffer.h"
+#include "tcg.h"
+
+// Helper code for the consts, eg. to produce messages for error codes.
+
+typedef struct error_code_entry_t {
+ TPM_RESULT code;
+ char * code_name;
+ char * msg;
+} error_code_entry_t;
+
+static const error_code_entry_t error_msgs [] = {
+ { TPM_SUCCESS, "TPM_SUCCESS", "Successful completion of the operation" },
+ { TPM_AUTHFAIL, "TPM_AUTHFAIL", "Authentication failed" },
+ { TPM_BADINDEX, "TPM_BADINDEX", "The index to a PCR, DIR or other register
is incorrect" },
+ { TPM_BAD_PARAMETER, "TPM_BAD_PARAMETER", "One or more parameter is bad" },
+ { TPM_AUDITFAILURE, "TPM_AUDITFAILURE", "An operation completed successfully
but the auditing of that operation failed." },
+ { TPM_CLEAR_DISABLED, "TPM_CLEAR_DISABLED", "The clear disable flag is set
and all clear operations now require physical access" },
+ { TPM_DEACTIVATED, "TPM_DEACTIVATED", "The TPM is deactivated" },
+ { TPM_DISABLED, "TPM_DISABLED", "The TPM is disabled" },
+ { TPM_DISABLED_CMD, "TPM_DISABLED_CMD", "The target command has been
disabled" },
+ { TPM_FAIL, "TPM_FAIL", "The operation failed" },
+ { TPM_BAD_ORDINAL, "TPM_BAD_ORDINAL", "The ordinal was unknown or
inconsistent" },
+ { TPM_INSTALL_DISABLED, "TPM_INSTALL_DISABLED", "The ability to install an
owner is disabled" },
+ { TPM_INVALID_KEYHANDLE, "TPM_INVALID_KEYHANDLE", "The key handle presented
was invalid" },
+ { TPM_KEYNOTFOUND, "TPM_KEYNOTFOUND", "The target key was not found" },
+ { TPM_INAPPROPRIATE_ENC, "TPM_INAPPROPRIATE_ENC", "Unacceptable encryption
scheme" },
+ { TPM_MIGRATEFAIL, "TPM_MIGRATEFAIL", "Migration authorization failed" },
+ { TPM_INVALID_PCR_INFO, "TPM_INVALID_PCR_INFO", "PCR information could not
be interpreted" },
+ { TPM_NOSPACE, "TPM_NOSPACE", "No room to load key." },
+ { TPM_NOSRK, "TPM_NOSRK", "There is no SRK set" },
+ { TPM_NOTSEALED_BLOB, "TPM_NOTSEALED_BLOB", "An encrypted blob is invalid or
was not created by this TPM" },
+ { TPM_OWNER_SET, "TPM_OWNER_SET", "There is already an Owner" },
+ { TPM_RESOURCES, "TPM_RESOURCES", "The TPM has insufficient internal
resources to perform the requested action." },
+ { TPM_SHORTRANDOM, "TPM_SHORTRANDOM", "A random string was too short" },
+ { TPM_SIZE, "TPM_SIZE", "The TPM does not have the space to perform the
operation." },
+ { TPM_WRONGPCRVAL, "TPM_WRONGPCRVAL", "The named PCR value does not match
the current PCR value." },
+ { TPM_BAD_PARAM_SIZE, "TPM_BAD_PARAM_SIZE", "The paramSize argument to the
command has the incorrect value" },
+ { TPM_SHA_THREAD, "TPM_SHA_THREAD", "There is no existing SHA-1 thread." },
+ { TPM_SHA_ERROR, "TPM_SHA_ERROR", "The calculation is unable to proceed
because the existing SHA-1 thread has already encountered an error." },
+ { TPM_FAILEDSELFTEST, "TPM_FAILEDSELFTEST", "Self-test has failed and the
TPM has shutdown." },
+ { TPM_AUTH2FAIL, "TPM_AUTH2FAIL", "The authorization for the second key in a
2 key function failed authorization" },
+ { TPM_BADTAG, "TPM_BADTAG", "The tag value sent to for a command is invalid"
},
+ { TPM_IOERROR, "TPM_IOERROR", "An IO error occurred transmitting information
to the TPM" },
+ { TPM_ENCRYPT_ERROR, "TPM_ENCRYPT_ERROR", "The encryption process had a
problem." },
+ { TPM_DECRYPT_ERROR, "TPM_DECRYPT_ERROR", "The decryption process did not
complete." },
+ { TPM_INVALID_AUTHHANDLE, "TPM_INVALID_AUTHHANDLE", "An invalid handle was
used." },
+ { TPM_NO_ENDORSEMENT, "TPM_NO_ENDORSEMENT", "The TPM does not a EK
installed" },
+ { TPM_INVALID_KEYUSAGE, "TPM_INVALID_KEYUSAGE", "The usage of a key is not
allowed" },
+ { TPM_WRONG_ENTITYTYPE, "TPM_WRONG_ENTITYTYPE", "The submitted entity type
is not allowed" },
+ { TPM_INVALID_POSTINIT, "TPM_INVALID_POSTINIT", "The command was received in
the wrong sequence relative to TPM_Init and a subsequent TPM_Startup" },
+ { TPM_INAPPROPRIATE_SIG, "TPM_INAPPROPRIATE_SIG", "Signed data cannot
include additional DER information" },
+ { TPM_BAD_KEY_PROPERTY, "TPM_BAD_KEY_PROPERTY", "The key properties in
TPM_KEY_PARMs are not supported by this TPM" },
+
+ { TPM_BAD_MIGRATION, "TPM_BAD_MIGRATION", "The migration properties of this
key are incorrect." },
+ { TPM_BAD_SCHEME, "TPM_BAD_SCHEME", "The signature or encryption scheme for
this key is incorrect or not permitted in this situation." },
+ { TPM_BAD_DATASIZE, "TPM_BAD_DATASIZE", "The size of the data (or blob)
parameter is bad or inconsistent with the referenced key" },
+ { TPM_BAD_MODE, "TPM_BAD_MODE", "A mode parameter is bad, such as capArea or
subCapArea for TPM_GetCapability, phsicalPresence parameter for
TPM_PhysicalPresence, or migrationType for TPM_CreateMigrationBlob." },
+ { TPM_BAD_PRESENCE, "TPM_BAD_PRESENCE", "Either the physicalPresence or
physicalPresenceLock bits have the wrong value" },
+ { TPM_BAD_VERSION, "TPM_BAD_VERSION", "The TPM cannot perform this version
of the capability" },
+ { TPM_NO_WRAP_TRANSPORT, "TPM_NO_WRAP_TRANSPORT", "The TPM does not allow
for wrapped transport sessions" },
+ { TPM_AUDITFAIL_UNSUCCESSFUL, "TPM_AUDITFAIL_UNSUCCESSFUL", "TPM audit
construction failed and the underlying command was returning a failure code
also" },
+ { TPM_AUDITFAIL_SUCCESSFUL, "TPM_AUDITFAIL_SUCCESSFUL", "TPM audit
construction failed and the underlying command was returning success" },
+ { TPM_NOTRESETABLE, "TPM_NOTRESETABLE", "Attempt to reset a PCR register
that does not have the resettable attribute" },
+ { TPM_NOTLOCAL, "TPM_NOTLOCAL", "Attempt to reset a PCR register that
requires locality and locality modifier not part of command transport" },
+ { TPM_BAD_TYPE, "TPM_BAD_TYPE", "Make identity blob not properly typed" },
+ { TPM_INVALID_RESOURCE, "TPM_INVALID_RESOURCE", "When saving context
identified resource type does not match actual resource" },
+ { TPM_NOTFIPS, "TPM_NOTFIPS", "The TPM is attempting to execute a command
only available when in FIPS mode" },
+ { TPM_INVALID_FAMILY, "TPM_INVALID_FAMILY", "The command is attempting to
use an invalid family ID" },
+ { TPM_NO_NV_PERMISSION, "TPM_NO_NV_PERMISSION", "The permission to
manipulate the NV storage is not available" },
+ { TPM_REQUIRES_SIGN, "TPM_REQUIRES_SIGN", "The operation requires a signed
command" },
+ { TPM_KEY_NOTSUPPORTED, "TPM_KEY_NOTSUPPORTED", "Wrong operation to load an
NV key" },
+ { TPM_AUTH_CONFLICT, "TPM_AUTH_CONFLICT", "NV_LoadKey blob requires both
owner and blob authorization" },
+ { TPM_AREA_LOCKED, "TPM_AREA_LOCKED", "The NV area is locked and not
writtable" },
+ { TPM_BAD_LOCALITY, "TPM_BAD_LOCALITY", "The locality is incorrect for the
attempted operation" },
+ { TPM_READ_ONLY, "TPM_READ_ONLY", "The NV area is read only and can't be
written to" },
+ { TPM_PER_NOWRITE, "TPM_PER_NOWRITE", "There is no protection on the write
to the NV area" },
+ { TPM_FAMILYCOUNT, "TPM_FAMILYCOUNT", "The family count value does not
match" },
+ { TPM_WRITE_LOCKED, "TPM_WRITE_LOCKED", "The NV area has already been
written to" },
+ { TPM_BAD_ATTRIBUTES, "TPM_BAD_ATTRIBUTES", "The NV area attributes
conflict" },
+ { TPM_INVALID_STRUCTURE, "TPM_INVALID_STRUCTURE", "The structure tag and
version are invalid or inconsistent" },
+ { TPM_KEY_OWNER_CONTROL, "TPM_KEY_OWNER_CONTROL", "The key is under control
of the TPM Owner and can only be evicted by the TPM Owner." },
+ { TPM_BAD_COUNTER, "TPM_BAD_COUNTER", "The counter handle is incorrect" },
+ { TPM_NOT_FULLWRITE, "TPM_NOT_FULLWRITE", "The write is not a complete write
of the area" },
+ { TPM_CONTEXT_GAP, "TPM_CONTEXT_GAP", "The gap between saved context counts
is too large" },
+ { TPM_MAXNVWRITES, "TPM_MAXNVWRITES", "The maximum number of NV writes
without an owner has been exceeded" },
+ { TPM_NOOPERATOR, "TPM_NOOPERATOR", "No operator authorization value is set"
},
+ { TPM_RESOURCEMISSING, "TPM_RESOURCEMISSING", "The resource pointed to by
context is not loaded" },
+ { TPM_DELEGATE_LOCK, "TPM_DELEGATE_LOCK", "The delegate administration is
locked" },
+ { TPM_DELEGATE_FAMILY, "TPM_DELEGATE_FAMILY", "Attempt to manage a family
other then the delegated family" },
+ { TPM_DELEGATE_ADMIN, "TPM_DELEGATE_ADMIN", "Delegation table management not
enabled" },
+ { TPM_TRANSPORT_EXCLUSIVE, "TPM_TRANSPORT_EXCLUSIVE", "There was a command
executed outside of an exclusive transport session" },
+};
+
+
+// helper function for the error codes:
+const char* tpm_get_error_name (TPM_RESULT code) {
+ // just do a linear scan for now
+ unsigned i;
+ for (i = 0; i < sizeof(error_msgs)/sizeof(error_msgs[0]); i++)
+ if (code == error_msgs[i].code)
+ return error_msgs[i].code_name;
+
+ return "Failed to find code name for given code";
+}
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/util/log.h
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/util/log.h Thu Sep 1 10:16:14 2005
@@ -0,0 +1,92 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+
+#ifndef __VTPM_LOG_H__
+#define __VTPM_LOG_H__
+
+#include <stdint.h> // for uint32_t
+#include <stddef.h> // for pointer NULL
+
+// =========================== LOGGING ==============================
+
+// the logging module numbers
+#define VTPM_LOG_CRYPTO 1
+#define VTPM_LOG_BSG 2
+#define VTPM_LOG_TXDATA 3
+#define VTPM_LOG_TCS 4
+#define VTPM_LOG_TCS_DEEP 5
+#define VTPM_LOG_VTSP 6
+#define VTPM_LOG_VTPM 7
+#define VTPM_LOG_VTPM_DEEP 8
+
+static char *module_names[] = { "",
+ "CRYPTO",
+ "BSG",
+ "TXDATA",
+ "TCS",
+ "TCS",
+ "VTSP",
+ "VTPM",
+ "VTPM"
+ };
+
+// Default to standard logging
+#ifndef LOGGING_MODULES
+#define LOGGING_MODULES (BITMASK(VTPM_LOG_VTPM))
+#endif
+
+// bit-access macros
+#define BITMASK(idx) ( 1U << (idx) )
+#define GETBIT(num,idx) ( ((num) & BITMASK(idx)) >> idx )
+#define SETBIT(num,idx) (num) |= BITMASK(idx)
+#define CLEARBIT(num,idx) (num) &= ( ~ BITMASK(idx) )
+
+#define vtpmloginfo(module, fmt, args...) \
+ if (GETBIT (LOGGING_MODULES, module) == 1) { \
+ fprintf (stdout, "INFO[%s]: " fmt, module_names[module], ##args); \
+ }
+
+#define vtpmloginfomore(module, fmt, args...) \
+ if (GETBIT (LOGGING_MODULES, module) == 1) { \
+ fprintf (stdout, fmt,##args); \
+ }
+
+#define vtpmlogerror(module, fmt, args...) \
+ fprintf (stderr, "ERROR[%s]: " fmt, module_names[module], ##args);
+
+//typedef UINT32 tpm_size_t;
+
+// helper function for the error codes:
+const char* tpm_get_error_name (TPM_RESULT code);
+
+#endif // _VTPM_LOG_H_
diff -r 84ab93e1ee05 -r dd668f7527cb tools/vtpm_manager/util/tcg.h
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/tools/vtpm_manager/util/tcg.h Thu Sep 1 10:16:14 2005
@@ -0,0 +1,486 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+//
+// tcg.h
+//
+// This file contains all the structure and type definitions
+//
+// ==================================================================
+
+#ifndef __TCG_H__
+#define __TCG_H__
+
+// This pragma is used to disallow structure padding
+#pragma pack(push, 1)
+
+// *************************** TYPEDEFS *********************************
+typedef unsigned char BYTE;
+typedef unsigned char BOOL;
+typedef unsigned short UINT16;
+typedef unsigned int UINT32;
+typedef unsigned long long UINT64;
+
+typedef UINT32 TPM_RESULT;
+typedef UINT32 TPM_PCRINDEX;
+typedef UINT32 TPM_DIRINDEX;
+typedef UINT32 TPM_HANDLE;
+typedef TPM_HANDLE TPM_AUTHHANDLE;
+typedef TPM_HANDLE TCPA_HASHHANDLE;
+typedef TPM_HANDLE TCPA_HMACHANDLE;
+typedef TPM_HANDLE TCPA_ENCHANDLE;
+typedef TPM_HANDLE TPM_KEY_HANDLE;
+typedef TPM_HANDLE TCPA_ENTITYHANDLE;
+typedef UINT32 TPM_RESOURCE_TYPE;
+typedef UINT32 TPM_COMMAND_CODE;
+typedef UINT16 TPM_PROTOCOL_ID;
+typedef BYTE TPM_AUTH_DATA_USAGE;
+typedef UINT16 TPM_ENTITY_TYPE;
+typedef UINT32 TPM_ALGORITHM_ID;
+typedef UINT16 TPM_KEY_USAGE;
+typedef UINT16 TPM_STARTUP_TYPE;
+typedef UINT32 TPM_CAPABILITY_AREA;
+typedef UINT16 TPM_ENC_SCHEME;
+typedef UINT16 TPM_SIG_SCHEME;
+typedef UINT16 TPM_MIGRATE_SCHEME;
+typedef UINT16 TPM_PHYSICAL_PRESENCE;
+typedef UINT32 TPM_KEY_FLAGS;
+
+#define TPM_DIGEST_SIZE 20 // Don't change this
+typedef BYTE TPM_AUTHDATA[TPM_DIGEST_SIZE];
+typedef TPM_AUTHDATA TPM_SECRET;
+typedef TPM_AUTHDATA TPM_ENCAUTH;
+typedef BYTE TPM_PAYLOAD_TYPE;
+typedef UINT16 TPM_TAG;
+
+// Data Types of the TCS
+typedef UINT32 TCS_AUTHHANDLE; // Handle addressing a authorization session
+typedef UINT32 TCS_CONTEXT_HANDLE; // Basic context handle
+typedef UINT32 TCS_KEY_HANDLE; // Basic key handle
+
+// ************************* STRUCTURES **********************************
+
+typedef struct TPM_VERSION {
+ BYTE major;
+ BYTE minor;
+ BYTE revMajor;
+ BYTE revMinor;
+} TPM_VERSION;
+
+static const TPM_VERSION TPM_STRUCT_VER_1_1 = { 1,1,0,0 };
+
+typedef struct TPM_DIGEST {
+ BYTE digest[TPM_DIGEST_SIZE];
+} TPM_DIGEST;
+
+typedef TPM_DIGEST TPM_PCRVALUE;
+typedef TPM_DIGEST TPM_COMPOSITE_HASH;
+typedef TPM_DIGEST TPM_DIRVALUE;
+typedef TPM_DIGEST TPM_HMAC;
+typedef TPM_DIGEST TPM_CHOSENID_HASH;
+
+typedef struct TPM_NONCE {
+ BYTE nonce[TPM_DIGEST_SIZE];
+} TPM_NONCE;
+
+typedef struct TPM_KEY_PARMS {
+ TPM_ALGORITHM_ID algorithmID;
+ TPM_ENC_SCHEME encScheme;
+ TPM_SIG_SCHEME sigScheme;
+ UINT32 parmSize;
+ BYTE* parms;
+} TPM_KEY_PARMS;
+
+typedef struct TPM_RSA_KEY_PARMS {
+ UINT32 keyLength;
+ UINT32 numPrimes;
+ UINT32 exponentSize;
+ BYTE* exponent;
+} TPM_RSA_KEY_PARMS;
+
+typedef struct TPM_STORE_PUBKEY {
+ UINT32 keyLength;
+ BYTE* key;
+} TPM_STORE_PUBKEY;
+
+typedef struct TPM_PUBKEY {
+ TPM_KEY_PARMS algorithmParms;
+ TPM_STORE_PUBKEY pubKey;
+} TPM_PUBKEY;
+
+typedef struct TPM_KEY {
+ TPM_VERSION ver;
+ TPM_KEY_USAGE keyUsage;
+ TPM_KEY_FLAGS keyFlags;
+ TPM_AUTH_DATA_USAGE authDataUsage;
+ TPM_KEY_PARMS algorithmParms;
+ UINT32 PCRInfoSize;
+ BYTE* PCRInfo; // this should be a TPM_PCR_INFO, or NULL
+ TPM_STORE_PUBKEY pubKey;
+ UINT32 encDataSize;
+ BYTE* encData;
+} TPM_KEY;
+
+typedef struct TPM_PCR_SELECTION {
+ UINT16 sizeOfSelect; /// in bytes
+ BYTE* pcrSelect;
+} TPM_PCR_SELECTION;
+
+typedef struct TPM_PCR_COMPOSITE {
+ TPM_PCR_SELECTION select;
+ UINT32 valueSize;
+ TPM_PCRVALUE* pcrValue;
+} TPM_PCR_COMPOSITE;
+
+
+typedef struct TPM_PCR_INFO {
+ TPM_PCR_SELECTION pcrSelection;
+ TPM_COMPOSITE_HASH digestAtRelease;
+ TPM_COMPOSITE_HASH digestAtCreation;
+} TPM_PCR_INFO;
+
+
+typedef struct TPM_BOUND_DATA {
+ TPM_VERSION ver;
+ TPM_PAYLOAD_TYPE payload;
+ BYTE* payloadData;
+} TPM_BOUND_DATA;
+
+typedef struct TPM_STORED_DATA {
+ TPM_VERSION ver;
+ UINT32 sealInfoSize;
+ BYTE* sealInfo;
+ UINT32 encDataSize;
+ BYTE* encData;
+} TPM_STORED_DATA;
+
+typedef struct TCS_AUTH {
+ TCS_AUTHHANDLE AuthHandle;
+ TPM_NONCE NonceOdd; // system
+ TPM_NONCE NonceEven; // TPM
+ BOOL fContinueAuthSession;
+ TPM_AUTHDATA HMAC;
+} TCS_AUTH;
+
+// **************************** CONSTANTS *********************************
+
+// BOOL values
+#define TRUE 0x01
+#define FALSE 0x00
+
+#define TCPA_MAX_BUFFER_LENGTH 0x2000
+
+//
+// TPM_COMMAND_CODE values
+#define TPM_PROTECTED_ORDINAL 0x00000000UL
+#define TPM_UNPROTECTED_ORDINAL 0x80000000UL
+#define TPM_CONNECTION_ORDINAL 0x40000000UL
+#define TPM_VENDOR_ORDINAL 0x20000000UL
+
+#define TPM_ORD_OIAP (10UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_OSAP (11UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ChangeAuth (12UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_TakeOwnership (13UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ChangeAuthAsymStart (14UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ChangeAuthAsymFinish (15UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ChangeAuthOwner (16UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Extend (20UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_PcrRead (21UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Quote (22UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Seal (23UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Unseal (24UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_DirWriteAuth (25UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_DirRead (26UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_UnBind (30UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_CreateWrapKey (31UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_LoadKey (32UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_GetPubKey (33UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_EvictKey (34UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_CreateMigrationBlob (40UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ReWrapKey (41UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ConvertMigrationBlob (42UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_AuthorizeMigrationKey (43UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_CreateMaintenanceArchive (44UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_LoadMaintenanceArchive (45UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_KillMaintenanceFeature (46UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_LoadManuMaintPub (47UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ReadManuMaintPub (48UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_CertifyKey (50UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Sign (60UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_GetRandom (70UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_StirRandom (71UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SelfTestFull (80UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SelfTestStartup (81UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_CertifySelfTest (82UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ContinueSelfTest (83UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_GetTestResult (84UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Reset (90UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_OwnerClear (91UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_DisableOwnerClear (92UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ForceClear (93UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_DisableForceClear (94UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_GetCapabilitySigned (100UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_GetCapability (101UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_GetCapabilityOwner (102UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_OwnerSetDisable (110UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_PhysicalEnable (111UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_PhysicalDisable (112UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SetOwnerInstall (113UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_PhysicalSetDeactivated (114UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SetTempDeactivated (115UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_CreateEndorsementKeyPair (120UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_MakeIdentity (121UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ActivateIdentity (122UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ReadPubek (124UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_OwnerReadPubek (125UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_DisablePubekRead (126UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_GetAuditEvent (130UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_GetAuditEventSigned (131UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_GetOrdinalAuditStatus (140UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SetOrdinalAuditStatus (141UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Terminate_Handle (150UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Init (151UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SaveState (152UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Startup (153UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SetRedirection (154UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SHA1Start (160UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SHA1Update (161UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SHA1Complete (162UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SHA1CompleteExtend (163UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_FieldUpgrade (170UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SaveKeyContext (180UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_LoadKeyContext (181UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SaveAuthContext (182UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_LoadAuthContext (183UL + TPM_PROTECTED_ORDINAL)
+#define TSC_ORD_PhysicalPresence (10UL + TPM_CONNECTION_ORDINAL)
+
+
+
+//
+// TPM_RESULT values
+//
+// just put in the whole table from spec 1.2
+
+#define TPM_BASE 0x0 // The start of TPM return codes
+#define TPM_VENDOR_ERROR 0x00000400 // Mask to indicate that the error code is
vendor specific for vendor specific commands
+#define TPM_NON_FATAL 0x00000800 // Mask to indicate that the error code is a
non-fatal failure.
+
+#define TPM_SUCCESS TPM_BASE // Successful completion of the operation
+#define TPM_AUTHFAIL TPM_BASE + 1 // Authentication failed
+#define TPM_BADINDEX TPM_BASE + 2 // The index to a PCR, DIR or other
register is incorrect
+#define TPM_BAD_PARAMETER TPM_BASE + 3 // One or more parameter is bad
+#define TPM_AUDITFAILURE TPM_BASE + 4 // An operation completed
successfully but the auditing of that operation failed.
+#define TPM_CLEAR_DISABLED TPM_BASE + 5 // The clear disable flag is set
and all clear operations now require physical access
+#define TPM_DEACTIVATED TPM_BASE + 6 // The TPM is deactivated
+#define TPM_DISABLED TPM_BASE + 7 // The TPM is disabled
+#define TPM_DISABLED_CMD TPM_BASE + 8 // The target command has been
disabled
+#define TPM_FAIL TPM_BASE + 9 // The operation failed
+#define TPM_BAD_ORDINAL TPM_BASE + 10 // The ordinal was unknown or
inconsistent
+#define TPM_INSTALL_DISABLED TPM_BASE + 11 // The ability to install an
owner is disabled
+#define TPM_INVALID_KEYHANDLE TPM_BASE + 12 // The key handle presented was
invalid
+#define TPM_KEYNOTFOUND TPM_BASE + 13 // The target key was not found
+#define TPM_INAPPROPRIATE_ENC TPM_BASE + 14 // Unacceptable encryption scheme
+#define TPM_MIGRATEFAIL TPM_BASE + 15 // Migration authorization failed
+#define TPM_INVALID_PCR_INFO TPM_BASE + 16 // PCR information could not be
interpreted
+#define TPM_NOSPACE TPM_BASE + 17 // No room to load key.
+#define TPM_NOSRK TPM_BASE + 18 // There is no SRK set
+#define TPM_NOTSEALED_BLOB TPM_BASE + 19 // An encrypted blob is invalid
or was not created by this TPM
+#define TPM_OWNER_SET TPM_BASE + 20 // There is already an Owner
+#define TPM_RESOURCES TPM_BASE + 21 // The TPM has insufficient internal
resources to perform the requested action.
+#define TPM_SHORTRANDOM TPM_BASE + 22 // A random string was too short
+#define TPM_SIZE TPM_BASE + 23 // The TPM does not have the space to
perform the operation.
+#define TPM_WRONGPCRVAL TPM_BASE + 24 // The named PCR value does not
match the current PCR value.
+#define TPM_BAD_PARAM_SIZE TPM_BASE + 25 // The paramSize argument to the
command has the incorrect value
+#define TPM_SHA_THREAD TPM_BASE + 26 // There is no existing SHA-1 thread.
+#define TPM_SHA_ERROR TPM_BASE + 27 // The calculation is unable to
proceed because the existing SHA-1 thread has already encountered an error.
+#define TPM_FAILEDSELFTEST TPM_BASE + 28 // Self-test has failed and the
TPM has shutdown.
+#define TPM_AUTH2FAIL TPM_BASE + 29 // The authorization for the second
key in a 2 key function failed authorization
+#define TPM_BADTAG TPM_BASE + 30 // The tag value sent to for a command
is invalid
+#define TPM_IOERROR TPM_BASE + 31 // An IO error occurred transmitting
information to the TPM
+#define TPM_ENCRYPT_ERROR TPM_BASE + 32 // The encryption process had a
problem.
+#define TPM_DECRYPT_ERROR TPM_BASE + 33 // The decryption process did not
complete.
+#define TPM_INVALID_AUTHHANDLE TPM_BASE + 34 // An invalid handle was used.
+#define TPM_NO_ENDORSEMENT TPM_BASE + 35 // The TPM does not a EK installed
+#define TPM_INVALID_KEYUSAGE TPM_BASE + 36 // The usage of a key is not
allowed
+#define TPM_WRONG_ENTITYTYPE TPM_BASE + 37 // The submitted entity type is
not allowed
+#define TPM_INVALID_POSTINIT TPM_BASE + 38 // The command was received in
the wrong sequence relative to TPM_Init and a subsequent TPM_Startup
+#define TPM_INAPPROPRIATE_SIG TPM_BASE + 39 // Signed data cannot include
additional DER information
+#define TPM_BAD_KEY_PROPERTY TPM_BASE + 40 // The key properties in
TPM_KEY_PARMs are not supported by this TPM
+
+#define TPM_BAD_MIGRATION TPM_BASE + 41 // The migration properties of
this key are incorrect.
+#define TPM_BAD_SCHEME TPM_BASE + 42 // The signature or encryption
scheme for this key is incorrect or not permitted in this situation.
+#define TPM_BAD_DATASIZE TPM_BASE + 43 // The size of the data (or blob)
parameter is bad or inconsistent with the referenced key
+#define TPM_BAD_MODE TPM_BASE + 44 // A mode parameter is bad, such as
capArea or subCapArea for TPM_GetCapability, phsicalPresence parameter for
TPM_PhysicalPresence, or migrationType for TPM_CreateMigrationBlob.
+#define TPM_BAD_PRESENCE TPM_BASE + 45 // Either the physicalPresence or
physicalPresenceLock bits have the wrong value
+#define TPM_BAD_VERSION TPM_BASE + 46 // The TPM cannot perform this
version of the capability
+#define TPM_NO_WRAP_TRANSPORT TPM_BASE + 47 // The TPM does not allow for
wrapped transport sessions
+#define TPM_AUDITFAIL_UNSUCCESSFUL TPM_BASE + 48 // TPM audit construction
failed and the underlying command was returning a failure code also
+#define TPM_AUDITFAIL_SUCCESSFUL TPM_BASE + 49 // TPM audit construction
failed and the underlying command was returning success
+#define TPM_NOTRESETABLE TPM_BASE + 50 // Attempt to reset a PCR register
that does not have the resettable attribute
+#define TPM_NOTLOCAL TPM_BASE + 51 // Attempt to reset a PCR register
that requires locality and locality modifier not part of command transport
+#define TPM_BAD_TYPE TPM_BASE + 52 // Make identity blob not properly
typed
+#define TPM_INVALID_RESOURCE TPM_BASE + 53 // When saving context
identified resource type does not match actual resource
+#define TPM_NOTFIPS TPM_BASE + 54 // The TPM is attempting to execute a
command only available when in FIPS mode
+#define TPM_INVALID_FAMILY TPM_BASE + 55 // The command is attempting to
use an invalid family ID
+#define TPM_NO_NV_PERMISSION TPM_BASE + 56 // The permission to manipulate
the NV storage is not available
+#define TPM_REQUIRES_SIGN TPM_BASE + 57 // The operation requires a
signed command
+#define TPM_KEY_NOTSUPPORTED TPM_BASE + 58 // Wrong operation to load an
NV key
+#define TPM_AUTH_CONFLICT TPM_BASE + 59 // NV_LoadKey blob requires both
owner and blob authorization
+#define TPM_AREA_LOCKED TPM_BASE + 60 // The NV area is locked and not
writtable
+#define TPM_BAD_LOCALITY TPM_BASE + 61 // The locality is incorrect for
the attempted operation
+#define TPM_READ_ONLY TPM_BASE + 62 // The NV area is read only and
can't be written to
+#define TPM_PER_NOWRITE TPM_BASE + 63 // There is no protection on the
write to the NV area
+#define TPM_FAMILYCOUNT TPM_BASE + 64 // The family count value does not
match
+#define TPM_WRITE_LOCKED TPM_BASE + 65 // The NV area has already been
written to
+#define TPM_BAD_ATTRIBUTES TPM_BASE + 66 // The NV area attributes
conflict
+#define TPM_INVALID_STRUCTURE TPM_BASE + 67 // The structure tag and
version are invalid or inconsistent
+#define TPM_KEY_OWNER_CONTROL TPM_BASE + 68 // The key is under control of
the TPM Owner and can only be evicted by the TPM Owner.
+#define TPM_BAD_COUNTER TPM_BASE + 69 // The counter handle is incorrect
+#define TPM_NOT_FULLWRITE TPM_BASE + 70 // The write is not a complete
write of the area
+#define TPM_CONTEXT_GAP TPM_BASE + 71 // The gap between saved context
counts is too large
+#define TPM_MAXNVWRITES TPM_BASE + 72 // The maximum number of NV writes
without an owner has been exceeded
+#define TPM_NOOPERATOR TPM_BASE + 73 // No operator authorization value
is set
+#define TPM_RESOURCEMISSING TPM_BASE + 74 // The resource pointed to by
context is not loaded
+#define TPM_DELEGATE_LOCK TPM_BASE + 75 // The delegate administration is
locked
+#define TPM_DELEGATE_FAMILY TPM_BASE + 76 // Attempt to manage a family
other then the delegated family
+#define TPM_DELEGATE_ADMIN TPM_BASE + 77 // Delegation table management
not enabled
+#define TPM_TRANSPORT_EXCLUSIVE TPM_BASE + 78 // There was a command
executed outside of an exclusive transport session
+
+// TPM_TAG values
+#define TPM_TAG_RQU_COMMAND 0x00c1
+#define TPM_TAG_RQU_AUTH1_COMMAND 0x00c2
+#define TPM_TAG_RQU_AUTH2_COMMAND 0x00c3
+#define TPM_TAG_RSP_COMMAND 0x00c4
+#define TPM_TAG_RSP_AUTH1_COMMAND 0x00c5
+#define TPM_TAG_RSP_AUTH2_COMMAND 0x00c6
+
+// TPM_PAYLOAD_TYPE values
+#define TPM_PT_ASYM 0x01
+#define TPM_PT_BIND 0x02
+#define TPM_PT_MIGRATE 0x03
+#define TPM_PT_MAINT 0x04
+#define TPM_PT_SEAL 0x05
+
+// TPM_ENTITY_TYPE values
+#define TPM_ET_KEYHANDLE 0x0001
+#define TPM_ET_OWNER 0x0002
+#define TPM_ET_DATA 0x0003
+#define TPM_ET_SRK 0x0004
+#define TPM_ET_KEY 0x0005
+
+/// TPM_ResourceTypes
+#define TPM_RT_KEY 0x00000001
+#define TPM_RT_AUTH 0x00000002
+#define TPM_RT_TRANS 0x00000004
+#define TPM_RT_CONTEXT 0x00000005
+
+// TPM_PROTOCOL_ID values
+#define TPM_PID_OIAP 0x0001
+#define TPM_PID_OSAP 0x0002
+#define TPM_PID_ADIP 0x0003
+#define TPM_PID_ADCP 0x0004
+#define TPM_PID_OWNER 0x0005
+
+// TPM_ALGORITHM_ID values
+#define TPM_ALG_RSA 0x00000001
+#define TPM_ALG_DES 0x00000002
+#define TPM_ALG_3DES 0X00000003
+#define TPM_ALG_SHA 0x00000004
+#define TPM_ALG_HMAC 0x00000005
+#define TCPA_ALG_AES 0x00000006
+
+// TPM_ENC_SCHEME values
+#define TPM_ES_NONE 0x0001
+#define TPM_ES_RSAESPKCSv15 0x0002
+#define TPM_ES_RSAESOAEP_SHA1_MGF1 0x0003
+
+// TPM_SIG_SCHEME values
+#define TPM_SS_NONE 0x0001
+#define TPM_SS_RSASSAPKCS1v15_SHA1 0x0002
+#define TPM_SS_RSASSAPKCS1v15_DER 0x0003
+
+// TPM_KEY_USAGE values
+#define TPM_KEY_EK 0x0000
+#define TPM_KEY_SIGNING 0x0010
+#define TPM_KEY_STORAGE 0x0011
+#define TPM_KEY_IDENTITY 0x0012
+#define TPM_KEY_AUTHCHANGE 0X0013
+#define TPM_KEY_BIND 0x0014
+#define TPM_KEY_LEGACY 0x0015
+
+// TPM_AUTH_DATA_USAGE values
+#define TPM_AUTH_NEVER 0x00
+#define TPM_AUTH_ALWAYS 0x01
+
+// Key Handle of owner and srk
+#define TPM_OWNER_KEYHANDLE 0x40000001
+#define TPM_SRK_KEYHANDLE 0x40000000
+
+// ---------------------- Functions for checking TPM_RESULTs -----------------
+
+// FIXME: Review use of these and delete unneeded ones.
+
+// these are really badly dependent on local structure:
+// DEPENDS: local var 'status' of type TPM_RESULT
+// DEPENDS: label 'abort_egress' which cleans up and returns the status
+#define ERRORDIE(s) do { status = s; \
+ fprintf (stderr, "*** ERRORDIE in %s, line %i\n",
__func__, __LINE__); \
+ goto abort_egress; } \
+ while (0)
+
+// ASSUME: the return value used after the abort_egress label has been set
+// already (eg. the 'status' local var)
+#define STATUSCHECK(s) if (s != TPM_SUCCESS) { \
+ fprintf (stderr, "*** ERR in %s, line %i\n",
__func__, __LINE__); \
+ goto abort_egress; \
+ }
+
+// DEPENDS: local var 'status' of type TPM_RESULT
+// DEPENDS: label 'abort_egress' which cleans up and returns the status
+// Try command c. If it fails, set status to s and goto shame.
+#define TPMTRY(s,c) if (c != TPM_SUCCESS) { \
+ status = s; \
+ goto abort_egress; \
+ }
+
+// Try command c. If it fails, print error message, set status to actual
return code. Goto shame
+#define TPMTRYRETURN(c) do { status = c; \
+ if (status != TPM_SUCCESS) { \
+ printf("ERROR in %s:%i code: %s.\n", __func__,
__LINE__, tpm_get_error_name(status)); \
+ goto abort_egress; \
+ } \
+ } while(0)
+
+
+#pragma pack(pop)
+
+#endif //__TCPA_H__
diff -r 84ab93e1ee05 -r dd668f7527cb xen/include/public/io/tpmif.h
--- /dev/null Thu Sep 1 10:08:53 2005
+++ b/xen/include/public/io/tpmif.h Thu Sep 1 10:16:14 2005
@@ -0,0 +1,42 @@
+/******************************************************************************
+ * tpmif.h
+ *
+ * TPM I/O interface for Xen guest OSes.
+ *
+ * Copyright (c) 2005, IBM Corporation
+ *
+ * Author: Stefan Berger, stefanb@xxxxxxxxxx
+ * Grant table support: Mahadevan Gomathisankaran
+ *
+ * This code has been derived from tools/libxc/xen/io/netif.h
+ *
+ * Copyright (c) 2003-2004, Keir Fraser
+ */
+
+#ifndef __XEN_PUBLIC_IO_TPMIF_H__
+#define __XEN_PUBLIC_IO_TPMIF_H__
+
+typedef struct {
+ unsigned long addr; /* Machine address of packet. */
+ int ref; /* grant table access reference */
+ u16 id; /* Echoed in response message. */
+ u16 size:15; /* Packet size in bytes. */
+ u16 mapped:1;
+} tpmif_tx_request_t;
+
+/*
+ * The TPMIF_TX_RING_SIZE defines the number of pages the
+ * front-end and backend can exchange (= size of array).
+ */
+typedef u32 TPMIF_RING_IDX;
+
+#define TPMIF_TX_RING_SIZE 16
+
+/* This structure must fit in a memory page. */
+typedef struct {
+ union {
+ tpmif_tx_request_t req;
+ } ring[TPMIF_TX_RING_SIZE];
+} tpmif_tx_interface_t;
+
+#endif
diff -r 84ab93e1ee05 -r dd668f7527cb tools/check/check_curl_devel
--- a/tools/check/check_curl_devel Thu Sep 1 10:08:53 2005
+++ /dev/null Thu Sep 1 10:16:14 2005
@@ -1,11 +0,0 @@
-#!/bin/bash
-# CHECK-BUILD
-
-function error {
- echo 'Check for libcurl includes failed.'
- exit 1
-}
-
-set -e
-[ -e /usr/include/curl ] || error
-[ -e /usr/include/curl/curl.h ] || error
\ No newline at end of file
diff -r 84ab93e1ee05 -r dd668f7527cb tools/check/check_curl_lib
--- a/tools/check/check_curl_lib Thu Sep 1 10:08:53 2005
+++ /dev/null Thu Sep 1 10:16:14 2005
@@ -1,10 +0,0 @@
-#!/bin/bash
-# CHECK-BUILD CHECK-INSTALL
-
-function error {
- echo 'Check for CURL library failed.'
- exit 1
-}
-
-set -e
-ldconfig -p | grep libcurl.so || error
\ No newline at end of file
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|