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

Side by Side Diff: tpmd_dev/darwin/tpm_bridge.c

Issue 660204: Upgrade to tpm-emulator version 0.7. (Closed)
Patch Set: Created 10 years, 9 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 unified diff | 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 »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2009-2010 Amit Singh. All Rights Reserved.
3 * http://osxbook.com
4 *
5 * TPM Emulator Device Bridge for Mac OS X
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR “AS IS” AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #include <sys/types.h>
29 #include <sys/fcntl.h>
30 #include <sys/systm.h>
31 #include <sys/conf.h>
32 #include <sys/ioctl.h>
33 #include <sys/param.h>
34 #include <sys/unistd.h>
35 #include <sys/malloc.h>
36 #include <sys/kpi_socket.h>
37 #include <sys/kpi_mbuf.h>
38 #include <sys/un.h>
39 #include <kern/locks.h>
40 #include <miscfs/devfs/devfs.h>
41 #include <mach/mach_types.h>
42 #include <libkern/OSAtomic.h>
43 #include "config.h"
44
45 /* configurable */
46
47 #define TPM_BRIDGE_NAME "tpm" /* bridge device file name (/dev/tpm) */
48 #define TPM_BRIDGE_MODE 0666 /* world readable/writable by default */
49 #define TPM_BRIDGE_UID UID_ROOT /* bridge device file owner ID */
50 #define TPM_BRIDGE_GID GID_WHEEL /* bridge device file group ID */
51
52 /* buffer */
53
54 static char tpm_buffer[TPM_CMD_BUF_SIZE] = { 0 };
55
56 /* locking */
57
58 static lck_grp_attr_t* tpm_mtx_grp_attr = NULL;
59 static lck_grp_t* tpm_mtx_grp = NULL;
60 static lck_attr_t* tpm_mtx_attr = NULL;
61 static lck_mtx_t* tpm_mtx = NULL;
62
63 /* user socket */
64
65 errno_t sock_nointerrupt(socket_t sock, int on);
66
67 static SInt32 tpm_activity = 0;
68 static UInt32 tpm_in_io = 0;
69 static socket_t tpmd_socket = 0;
70
71 static struct sockaddr_un tpmd_socket_addr = {
72 sizeof(struct sockaddr_un),
73 AF_LOCAL,
74 TPM_SOCKET_NAME,
75 };
76
77 /* device */
78
79 static int dev_tpm_index = -1;
80 static const int dev_tpm_minor = 0;
81 static void* dev_tpm_node = NULL;
82
83 d_open_t tpm_dev_open;
84 d_read_t tpm_dev_read;
85 d_write_t tpm_dev_write;
86 extern int seltrue(dev_t, int, struct proc*);
87
88 static struct cdevsw cdev_tpm = {
89 tpm_dev_open,
90 (d_close_t*)&nulldev,
91 tpm_dev_read,
92 tpm_dev_write,
93 (d_ioctl_t*)&enodev,
94 (d_stop_t*)&nulldev,
95 (d_reset_t*)&nulldev,
96 0,
97 (select_fcn_t*)seltrue,
98 eno_mmap,
99 eno_strat,
100 eno_getc,
101 eno_putc,
102 D_TTY,
103 };
104
105 static int tpmd_connect(void);
106 static void tpmd_disconnect(void);
107 kern_return_t tpm_bridge_start(kmod_info_t* ki, void* d);
108 kern_return_t tpm_bridge_stop(kmod_info_t* ki, void* d);
109 static int tpm_bridge_locking_start(void);
110 static int tpm_bridge_locking_stop(void);
111 static int tpm_bridge_devfs_start(void);
112 static int tpm_bridge_devfs_stop(void);
113
114 int
115 tpm_dev_open(dev_t dev, int flags, int devtype, struct proc* p)
116 {
117 (void)OSIncrementAtomic(&tpm_activity);
118
119 int error = 0;
120
121 lck_mtx_lock(tpm_mtx);
122
123 if ((tpmd_socket == NULL) || !sock_isconnected(tpmd_socket)) {
124 if (tpmd_connect() != 0) {
125 tpmd_socket = NULL;
126 lck_mtx_unlock(tpm_mtx);
127 error = ECONNREFUSED;
128 goto out;
129 }
130 }
131
132 lck_mtx_unlock(tpm_mtx);
133
134 out:
135
136 (void)OSDecrementAtomic(&tpm_activity);
137
138 return error;
139 }
140
141 int
142 tpm_dev_read(dev_t dev, struct uio* uio, int ioflag)
143 {
144 (void)OSIncrementAtomic(&tpm_activity);
145
146 errno_t error = 0;
147 size_t recvlen;
148 struct msghdr msg;
149 struct iovec aiov[1];
150
151 lck_mtx_lock(tpm_mtx);
152
153 if ((tpmd_socket == NULL) || !sock_isconnected(tpmd_socket)) {
154 lck_mtx_unlock(tpm_mtx);
155 error = ENOTCONN;
156 goto out;
157 }
158
159 if (tpm_in_io) {
160 error = msleep(&tpm_in_io, tpm_mtx, PCATCH, "tpm_in_io", NULL);
161 if (error != 0) {
162 lck_mtx_unlock(tpm_mtx);
163 error = EAGAIN;
164 goto out;
165 }
166 }
167
168 tpm_in_io = 1;
169
170 lck_mtx_unlock(tpm_mtx);
171
172 (void)sock_nointerrupt(tpmd_socket, 1);
173
174 recvlen = (uint32_t)uio_resid(uio);
175
176 memset(&msg, 0, sizeof(msg));
177 aiov[0].iov_base = (caddr_t)tpm_buffer;
178 aiov[0].iov_len = TPM_CMD_BUF_SIZE;
179 if (recvlen < TPM_CMD_BUF_SIZE) {
180 aiov[0].iov_len = recvlen;
181 }
182 msg.msg_iovlen = 1;
183 msg.msg_iov = aiov;
184
185 if ((error = sock_receive(tpmd_socket, &msg, 0, (size_t*)&recvlen)) == 0) {
186 error = uiomove64((addr64_t)(uintptr_t)tpm_buffer, (int)recvlen, uio);
187 }
188
189 lck_mtx_lock(tpm_mtx);
190 tpm_in_io = 0;
191 wakeup_one((caddr_t)&tpm_in_io);
192 lck_mtx_unlock(tpm_mtx);
193
194 out:
195
196 (void)OSDecrementAtomic(&tpm_activity);
197
198 return error;
199 }
200
201 int
202 tpm_dev_write(dev_t dev, struct uio* uio, int ioflag)
203 {
204 (void)OSIncrementAtomic(&tpm_activity);
205
206 errno_t error = 0;
207 size_t sentlen;
208 struct msghdr msg;
209 struct iovec aiov[1];
210
211 lck_mtx_lock(tpm_mtx);
212
213 if ((tpmd_socket == NULL) || !sock_isconnected(tpmd_socket)) {
214 lck_mtx_unlock(tpm_mtx);
215 error = ENOTCONN;
216 goto out;
217 }
218
219 if (tpm_in_io) {
220 error = msleep(&tpm_in_io, tpm_mtx, PCATCH, "tpm_in_io", NULL);
221 if (error != 0) {
222 lck_mtx_unlock(tpm_mtx);
223 error = EAGAIN;
224 goto out;
225 }
226 }
227
228 tpm_in_io = 1;
229
230 lck_mtx_unlock(tpm_mtx);
231
232 sentlen = min((uint32_t)uio_resid(uio), TPM_CMD_BUF_SIZE);
233
234 if ((error = uiomove64((addr64_t)(uintptr_t)tpm_buffer,
235 (int)sentlen, uio)) == 0) {
236 memset(&msg, 0, sizeof(msg));
237 aiov[0].iov_base = (caddr_t)tpm_buffer;
238 aiov[0].iov_len = sentlen;
239 msg.msg_iovlen = 1;
240 msg.msg_iov = aiov;
241 error = sock_send(tpmd_socket, &msg, 0, &sentlen);
242 }
243
244 lck_mtx_lock(tpm_mtx);
245 tpm_in_io = 0;
246 wakeup_one((caddr_t)&tpm_in_io);
247 lck_mtx_unlock(tpm_mtx);
248
249 out:
250
251 (void)OSDecrementAtomic(&tpm_activity);
252
253 return error;
254 }
255
256 static int
257 tpmd_connect(void)
258 {
259 errno_t error;
260 struct timeval tv;
261
262 error = sock_socket(PF_LOCAL, SOCK_STREAM, 0, NULL, NULL, &tpmd_socket);
263 if (error != 0) {
264 tpmd_socket = NULL;
265 return error;
266 }
267
268 tv.tv_sec = 10;
269 tv.tv_usec = 0;
270 error = sock_setsockopt(tpmd_socket, SOL_SOCKET, SO_RCVTIMEO, &tv,
271 sizeof(struct timeval));
272 if (error != 0) {
273 sock_close(tpmd_socket);
274 tpmd_socket = NULL;
275 return error;
276 }
277
278 error = sock_connect(tpmd_socket,
279 (const struct sockaddr*)&tpmd_socket_addr, 0);
280 if (error != 0) {
281 sock_close(tpmd_socket);
282 tpmd_socket = NULL;
283 return error;
284 }
285
286 return 0;
287 }
288
289 static void
290 tpmd_disconnect(void)
291 {
292 if (tpmd_socket != NULL) {
293 sock_shutdown(tpmd_socket, SHUT_RDWR);
294 sock_close(tpmd_socket);
295 tpmd_socket = NULL;
296 }
297 }
298
299 static int
300 tpm_bridge_locking_start(void)
301 {
302 tpm_mtx_grp_attr = lck_grp_attr_alloc_init();
303 if (tpm_mtx_grp_attr == NULL) {
304 goto failed;
305 }
306
307 tpm_mtx_grp = lck_grp_alloc_init("tpm_mtx", tpm_mtx_grp_attr);
308 if (tpm_mtx_grp == NULL) {
309 goto failed;
310 }
311
312 tpm_mtx_attr = lck_attr_alloc_init();
313 if (tpm_mtx_attr == NULL) {
314 goto failed;
315 }
316
317 tpm_mtx = lck_mtx_alloc_init(tpm_mtx_grp, tpm_mtx_attr);
318 if (tpm_mtx == NULL) {
319 goto failed;
320 }
321
322 return KERN_SUCCESS;
323
324 failed:
325
326 (void)tpm_bridge_locking_stop();
327
328 return KERN_FAILURE;
329 }
330
331 static int
332 tpm_bridge_locking_stop(void)
333 {
334 if (tpm_mtx != NULL) {
335 lck_mtx_free(tpm_mtx, tpm_mtx_grp);
336 tpm_mtx = NULL;
337 }
338
339 if (tpm_mtx_attr != NULL) {
340 lck_attr_free(tpm_mtx_attr);
341 tpm_mtx_attr = NULL;
342 }
343
344 if (tpm_mtx_grp != NULL) {
345 lck_grp_free(tpm_mtx_grp);
346 tpm_mtx_grp = NULL;
347 }
348
349 if (tpm_mtx_grp_attr != NULL) {
350 lck_grp_attr_free(tpm_mtx_grp_attr);
351 tpm_mtx_grp_attr = NULL;
352 }
353
354 return KERN_SUCCESS;
355 }
356
357 static int
358 tpm_bridge_devfs_start(void)
359 {
360 dev_tpm_index = cdevsw_add(-1, &cdev_tpm);
361 if (dev_tpm_index == -1) {
362 return KERN_FAILURE;
363 }
364
365 dev_tpm_node = devfs_make_node(makedev(dev_tpm_index, dev_tpm_minor),
366 DEVFS_CHAR, TPM_BRIDGE_UID, TPM_BRIDGE_GID,
367 TPM_BRIDGE_MODE, TPM_BRIDGE_NAME);
368 if (dev_tpm_node == NULL) {
369 (void)tpm_bridge_devfs_stop();
370 return KERN_FAILURE;
371 }
372
373 return KERN_SUCCESS;
374 }
375
376 static int
377 tpm_bridge_devfs_stop(void)
378 {
379 int ret = KERN_SUCCESS;
380
381 if (dev_tpm_node != NULL) {
382 devfs_remove(dev_tpm_node);
383 dev_tpm_node = NULL;
384 }
385
386 if (dev_tpm_index != -1) {
387 ret = cdevsw_remove(dev_tpm_index, &cdev_tpm);
388 if (ret != dev_tpm_index) {
389 ret = KERN_FAILURE;
390 } else {
391 dev_tpm_index = -1;
392 ret = KERN_SUCCESS;
393 }
394 }
395
396 return ret;
397 }
398
399 kern_return_t
400 tpm_bridge_start(kmod_info_t* ki, void* d)
401 {
402 if (tpm_bridge_locking_start() != KERN_SUCCESS) {
403 return KERN_FAILURE;
404 }
405
406 if (tpm_bridge_devfs_start() != KERN_SUCCESS) {
407 tpm_bridge_locking_stop();
408 return KERN_FAILURE;
409 }
410
411 #ifndef SUN_LEN
412 #define SUN_LEN(su) \
413 (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
414 #define SUN_LEN_PRIVATELY_DEFINED 1
415 #endif
416
417 tpmd_socket_addr.sun_len = SUN_LEN(&tpmd_socket_addr);
418
419 #if SUN_LEN_PRIVATELY_DEFINED
420 #undef SUN_LEN
421 #endif
422
423 return KERN_SUCCESS;
424 }
425
426 kern_return_t
427 tpm_bridge_stop(kmod_info_t* ki, void* d)
428 {
429 lck_mtx_lock(tpm_mtx);
430
431 (void)tpm_bridge_devfs_stop();
432
433 if ((tpmd_socket != NULL) && sock_isconnected(tpmd_socket)) {
434 tpmd_disconnect();
435 tpmd_socket = NULL;
436 }
437
438 lck_mtx_unlock(tpm_mtx);
439
440 do {
441 struct timespec ts = { 1, 0 };
442 (void)msleep(&tpm_activity, NULL, PUSER, "tpm_activity", &ts);
443 } while (tpm_activity > 0);
444
445
446 (void)tpm_bridge_locking_stop();
447
448 return KERN_SUCCESS;
449 }
OLDNEW
« 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