[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] merge?
# 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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |