Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(254)

Unified Diff: tpmd_dev/darwin/tpm_bridge.c

Issue 660204: Upgrade to tpm-emulator version 0.7. (Closed)
Patch Set: Created 10 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tpmd_dev/darwin/Makefile ('k') | tpmd_dev/darwin/tpm_bridge.xcodeproj/TemplateIcon.tiff » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tpmd_dev/darwin/tpm_bridge.c
diff --git a/tpmd_dev/darwin/tpm_bridge.c b/tpmd_dev/darwin/tpm_bridge.c
new file mode 100644
index 0000000000000000000000000000000000000000..5dc923965c14195e315e0b72e9971ba7d8e392bc
--- /dev/null
+++ b/tpmd_dev/darwin/tpm_bridge.c
@@ -0,0 +1,449 @@
+/*
+ * Copyright (c) 2009-2010 Amit Singh. All Rights Reserved.
+ * http://osxbook.com
+ *
+ * TPM Emulator Device Bridge for Mac OS X
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR “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 AUTHOR 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 <sys/types.h>
+#include <sys/fcntl.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/ioctl.h>
+#include <sys/param.h>
+#include <sys/unistd.h>
+#include <sys/malloc.h>
+#include <sys/kpi_socket.h>
+#include <sys/kpi_mbuf.h>
+#include <sys/un.h>
+#include <kern/locks.h>
+#include <miscfs/devfs/devfs.h>
+#include <mach/mach_types.h>
+#include <libkern/OSAtomic.h>
+#include "config.h"
+
+/* configurable */
+
+#define TPM_BRIDGE_NAME "tpm" /* bridge device file name (/dev/tpm) */
+#define TPM_BRIDGE_MODE 0666 /* world readable/writable by default */
+#define TPM_BRIDGE_UID UID_ROOT /* bridge device file owner ID */
+#define TPM_BRIDGE_GID GID_WHEEL /* bridge device file group ID */
+
+/* buffer */
+
+static char tpm_buffer[TPM_CMD_BUF_SIZE] = { 0 };
+
+/* locking */
+
+static lck_grp_attr_t* tpm_mtx_grp_attr = NULL;
+static lck_grp_t* tpm_mtx_grp = NULL;
+static lck_attr_t* tpm_mtx_attr = NULL;
+static lck_mtx_t* tpm_mtx = NULL;
+
+/* user socket */
+
+errno_t sock_nointerrupt(socket_t sock, int on);
+
+static SInt32 tpm_activity = 0;
+static UInt32 tpm_in_io = 0;
+static socket_t tpmd_socket = 0;
+
+static struct sockaddr_un tpmd_socket_addr = {
+ sizeof(struct sockaddr_un),
+ AF_LOCAL,
+ TPM_SOCKET_NAME,
+};
+
+/* device */
+
+static int dev_tpm_index = -1;
+static const int dev_tpm_minor = 0;
+static void* dev_tpm_node = NULL;
+
+d_open_t tpm_dev_open;
+d_read_t tpm_dev_read;
+d_write_t tpm_dev_write;
+extern int seltrue(dev_t, int, struct proc*);
+
+static struct cdevsw cdev_tpm = {
+ tpm_dev_open,
+ (d_close_t*)&nulldev,
+ tpm_dev_read,
+ tpm_dev_write,
+ (d_ioctl_t*)&enodev,
+ (d_stop_t*)&nulldev,
+ (d_reset_t*)&nulldev,
+ 0,
+ (select_fcn_t*)seltrue,
+ eno_mmap,
+ eno_strat,
+ eno_getc,
+ eno_putc,
+ D_TTY,
+};
+
+static int tpmd_connect(void);
+static void tpmd_disconnect(void);
+kern_return_t tpm_bridge_start(kmod_info_t* ki, void* d);
+kern_return_t tpm_bridge_stop(kmod_info_t* ki, void* d);
+static int tpm_bridge_locking_start(void);
+static int tpm_bridge_locking_stop(void);
+static int tpm_bridge_devfs_start(void);
+static int tpm_bridge_devfs_stop(void);
+
+int
+tpm_dev_open(dev_t dev, int flags, int devtype, struct proc* p)
+{
+ (void)OSIncrementAtomic(&tpm_activity);
+
+ int error = 0;
+
+ lck_mtx_lock(tpm_mtx);
+
+ if ((tpmd_socket == NULL) || !sock_isconnected(tpmd_socket)) {
+ if (tpmd_connect() != 0) {
+ tpmd_socket = NULL;
+ lck_mtx_unlock(tpm_mtx);
+ error = ECONNREFUSED;
+ goto out;
+ }
+ }
+
+ lck_mtx_unlock(tpm_mtx);
+
+out:
+
+ (void)OSDecrementAtomic(&tpm_activity);
+
+ return error;
+}
+
+int
+tpm_dev_read(dev_t dev, struct uio* uio, int ioflag)
+{
+ (void)OSIncrementAtomic(&tpm_activity);
+
+ errno_t error = 0;
+ size_t recvlen;
+ struct msghdr msg;
+ struct iovec aiov[1];
+
+ lck_mtx_lock(tpm_mtx);
+
+ if ((tpmd_socket == NULL) || !sock_isconnected(tpmd_socket)) {
+ lck_mtx_unlock(tpm_mtx);
+ error = ENOTCONN;
+ goto out;
+ }
+
+ if (tpm_in_io) {
+ error = msleep(&tpm_in_io, tpm_mtx, PCATCH, "tpm_in_io", NULL);
+ if (error != 0) {
+ lck_mtx_unlock(tpm_mtx);
+ error = EAGAIN;
+ goto out;
+ }
+ }
+
+ tpm_in_io = 1;
+
+ lck_mtx_unlock(tpm_mtx);
+
+ (void)sock_nointerrupt(tpmd_socket, 1);
+
+ recvlen = (uint32_t)uio_resid(uio);
+
+ memset(&msg, 0, sizeof(msg));
+ aiov[0].iov_base = (caddr_t)tpm_buffer;
+ aiov[0].iov_len = TPM_CMD_BUF_SIZE;
+ if (recvlen < TPM_CMD_BUF_SIZE) {
+ aiov[0].iov_len = recvlen;
+ }
+ msg.msg_iovlen = 1;
+ msg.msg_iov = aiov;
+
+ if ((error = sock_receive(tpmd_socket, &msg, 0, (size_t*)&recvlen)) == 0) {
+ error = uiomove64((addr64_t)(uintptr_t)tpm_buffer, (int)recvlen, uio);
+ }
+
+ lck_mtx_lock(tpm_mtx);
+ tpm_in_io = 0;
+ wakeup_one((caddr_t)&tpm_in_io);
+ lck_mtx_unlock(tpm_mtx);
+
+out:
+
+ (void)OSDecrementAtomic(&tpm_activity);
+
+ return error;
+}
+
+int
+tpm_dev_write(dev_t dev, struct uio* uio, int ioflag)
+{
+ (void)OSIncrementAtomic(&tpm_activity);
+
+ errno_t error = 0;
+ size_t sentlen;
+ struct msghdr msg;
+ struct iovec aiov[1];
+
+ lck_mtx_lock(tpm_mtx);
+
+ if ((tpmd_socket == NULL) || !sock_isconnected(tpmd_socket)) {
+ lck_mtx_unlock(tpm_mtx);
+ error = ENOTCONN;
+ goto out;
+ }
+
+ if (tpm_in_io) {
+ error = msleep(&tpm_in_io, tpm_mtx, PCATCH, "tpm_in_io", NULL);
+ if (error != 0) {
+ lck_mtx_unlock(tpm_mtx);
+ error = EAGAIN;
+ goto out;
+ }
+ }
+
+ tpm_in_io = 1;
+
+ lck_mtx_unlock(tpm_mtx);
+
+ sentlen = min((uint32_t)uio_resid(uio), TPM_CMD_BUF_SIZE);
+
+ if ((error = uiomove64((addr64_t)(uintptr_t)tpm_buffer,
+ (int)sentlen, uio)) == 0) {
+ memset(&msg, 0, sizeof(msg));
+ aiov[0].iov_base = (caddr_t)tpm_buffer;
+ aiov[0].iov_len = sentlen;
+ msg.msg_iovlen = 1;
+ msg.msg_iov = aiov;
+ error = sock_send(tpmd_socket, &msg, 0, &sentlen);
+ }
+
+ lck_mtx_lock(tpm_mtx);
+ tpm_in_io = 0;
+ wakeup_one((caddr_t)&tpm_in_io);
+ lck_mtx_unlock(tpm_mtx);
+
+out:
+
+ (void)OSDecrementAtomic(&tpm_activity);
+
+ return error;
+}
+
+static int
+tpmd_connect(void)
+{
+ errno_t error;
+ struct timeval tv;
+
+ error = sock_socket(PF_LOCAL, SOCK_STREAM, 0, NULL, NULL, &tpmd_socket);
+ if (error != 0) {
+ tpmd_socket = NULL;
+ return error;
+ }
+
+ tv.tv_sec = 10;
+ tv.tv_usec = 0;
+ error = sock_setsockopt(tpmd_socket, SOL_SOCKET, SO_RCVTIMEO, &tv,
+ sizeof(struct timeval));
+ if (error != 0) {
+ sock_close(tpmd_socket);
+ tpmd_socket = NULL;
+ return error;
+ }
+
+ error = sock_connect(tpmd_socket,
+ (const struct sockaddr*)&tpmd_socket_addr, 0);
+ if (error != 0) {
+ sock_close(tpmd_socket);
+ tpmd_socket = NULL;
+ return error;
+ }
+
+ return 0;
+}
+
+static void
+tpmd_disconnect(void)
+{
+ if (tpmd_socket != NULL) {
+ sock_shutdown(tpmd_socket, SHUT_RDWR);
+ sock_close(tpmd_socket);
+ tpmd_socket = NULL;
+ }
+}
+
+static int
+tpm_bridge_locking_start(void)
+{
+ tpm_mtx_grp_attr = lck_grp_attr_alloc_init();
+ if (tpm_mtx_grp_attr == NULL) {
+ goto failed;
+ }
+
+ tpm_mtx_grp = lck_grp_alloc_init("tpm_mtx", tpm_mtx_grp_attr);
+ if (tpm_mtx_grp == NULL) {
+ goto failed;
+ }
+
+ tpm_mtx_attr = lck_attr_alloc_init();
+ if (tpm_mtx_attr == NULL) {
+ goto failed;
+ }
+
+ tpm_mtx = lck_mtx_alloc_init(tpm_mtx_grp, tpm_mtx_attr);
+ if (tpm_mtx == NULL) {
+ goto failed;
+ }
+
+ return KERN_SUCCESS;
+
+failed:
+
+ (void)tpm_bridge_locking_stop();
+
+ return KERN_FAILURE;
+}
+
+static int
+tpm_bridge_locking_stop(void)
+{
+ if (tpm_mtx != NULL) {
+ lck_mtx_free(tpm_mtx, tpm_mtx_grp);
+ tpm_mtx = NULL;
+ }
+
+ if (tpm_mtx_attr != NULL) {
+ lck_attr_free(tpm_mtx_attr);
+ tpm_mtx_attr = NULL;
+ }
+
+ if (tpm_mtx_grp != NULL) {
+ lck_grp_free(tpm_mtx_grp);
+ tpm_mtx_grp = NULL;
+ }
+
+ if (tpm_mtx_grp_attr != NULL) {
+ lck_grp_attr_free(tpm_mtx_grp_attr);
+ tpm_mtx_grp_attr = NULL;
+ }
+
+ return KERN_SUCCESS;
+}
+
+static int
+tpm_bridge_devfs_start(void)
+{
+ dev_tpm_index = cdevsw_add(-1, &cdev_tpm);
+ if (dev_tpm_index == -1) {
+ return KERN_FAILURE;
+ }
+
+ dev_tpm_node = devfs_make_node(makedev(dev_tpm_index, dev_tpm_minor),
+ DEVFS_CHAR, TPM_BRIDGE_UID, TPM_BRIDGE_GID,
+ TPM_BRIDGE_MODE, TPM_BRIDGE_NAME);
+ if (dev_tpm_node == NULL) {
+ (void)tpm_bridge_devfs_stop();
+ return KERN_FAILURE;
+ }
+
+ return KERN_SUCCESS;
+}
+
+static int
+tpm_bridge_devfs_stop(void)
+{
+ int ret = KERN_SUCCESS;
+
+ if (dev_tpm_node != NULL) {
+ devfs_remove(dev_tpm_node);
+ dev_tpm_node = NULL;
+ }
+
+ if (dev_tpm_index != -1) {
+ ret = cdevsw_remove(dev_tpm_index, &cdev_tpm);
+ if (ret != dev_tpm_index) {
+ ret = KERN_FAILURE;
+ } else {
+ dev_tpm_index = -1;
+ ret = KERN_SUCCESS;
+ }
+ }
+
+ return ret;
+}
+
+kern_return_t
+tpm_bridge_start(kmod_info_t* ki, void* d)
+{
+ if (tpm_bridge_locking_start() != KERN_SUCCESS) {
+ return KERN_FAILURE;
+ }
+
+ if (tpm_bridge_devfs_start() != KERN_SUCCESS) {
+ tpm_bridge_locking_stop();
+ return KERN_FAILURE;
+ }
+
+#ifndef SUN_LEN
+#define SUN_LEN(su) \
+ (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
+#define SUN_LEN_PRIVATELY_DEFINED 1
+#endif
+
+ tpmd_socket_addr.sun_len = SUN_LEN(&tpmd_socket_addr);
+
+#if SUN_LEN_PRIVATELY_DEFINED
+#undef SUN_LEN
+#endif
+
+ return KERN_SUCCESS;
+}
+
+kern_return_t
+tpm_bridge_stop(kmod_info_t* ki, void* d)
+{
+ lck_mtx_lock(tpm_mtx);
+
+ (void)tpm_bridge_devfs_stop();
+
+ if ((tpmd_socket != NULL) && sock_isconnected(tpmd_socket)) {
+ tpmd_disconnect();
+ tpmd_socket = NULL;
+ }
+
+ lck_mtx_unlock(tpm_mtx);
+
+ do {
+ struct timespec ts = { 1, 0 };
+ (void)msleep(&tpm_activity, NULL, PUSER, "tpm_activity", &ts);
+ } while (tpm_activity > 0);
+
+
+ (void)tpm_bridge_locking_stop();
+
+ return KERN_SUCCESS;
+}
« no previous file with comments | « tpmd_dev/darwin/Makefile ('k') | tpmd_dev/darwin/tpm_bridge.xcodeproj/TemplateIcon.tiff » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698