// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2015, 2016 IBM Corporation * Copyright (C) 2016 Intel Corporation * * Author: Stefan Berger <[email protected]> * * Maintained by: <[email protected]> * * Device driver for vTPM (vTPM proxy driver) */ #include <linux/types.h> #include <linux/spinlock.h> #include <linux/uaccess.h> #include <linux/wait.h> #include <linux/miscdevice.h> #include <linux/vtpm_proxy.h> #include <linux/file.h> #include <linux/anon_inodes.h> #include <linux/poll.h> #include <linux/compat.h> #include "tpm.h" #define VTPM_PROXY_REQ_COMPLETE_FLAG … struct proxy_dev { … }; /* all supported flags */ #define VTPM_PROXY_FLAGS_ALL … static struct workqueue_struct *workqueue; static void vtpm_proxy_delete_device(struct proxy_dev *proxy_dev); /* * Functions related to 'server side' */ /** * vtpm_proxy_fops_read - Read TPM commands on 'server side' * * @filp: file pointer * @buf: read buffer * @count: number of bytes to read * @off: offset * * Return: * Number of bytes read or negative error code */ static ssize_t vtpm_proxy_fops_read(struct file *filp, char __user *buf, size_t count, loff_t *off) { … } /** * vtpm_proxy_fops_write - Write TPM responses on 'server side' * * @filp: file pointer * @buf: write buffer * @count: number of bytes to write * @off: offset * * Return: * Number of bytes read or negative error value */ static ssize_t vtpm_proxy_fops_write(struct file *filp, const char __user *buf, size_t count, loff_t *off) { … } /* * vtpm_proxy_fops_poll - Poll status on 'server side' * * @filp: file pointer * @wait: poll table * * Return: Poll flags */ static __poll_t vtpm_proxy_fops_poll(struct file *filp, poll_table *wait) { … } /* * vtpm_proxy_fops_open - Open vTPM device on 'server side' * * @filp: file pointer * * Called when setting up the anonymous file descriptor */ static void vtpm_proxy_fops_open(struct file *filp) { … } /** * vtpm_proxy_fops_undo_open - counter-part to vtpm_fops_open * Call to undo vtpm_proxy_fops_open * *@proxy_dev: tpm proxy device */ static void vtpm_proxy_fops_undo_open(struct proxy_dev *proxy_dev) { … } /* * vtpm_proxy_fops_release - Close 'server side' * * @inode: inode * @filp: file pointer * Return: * Always returns 0. */ static int vtpm_proxy_fops_release(struct inode *inode, struct file *filp) { … } static const struct file_operations vtpm_proxy_fops = …; /* * Functions invoked by the core TPM driver to send TPM commands to * 'server side' and receive responses from there. */ /* * Called when core TPM driver reads TPM responses from 'server side' * * @chip: tpm chip to use * @buf: receive buffer * @count: bytes to read * Return: * Number of TPM response bytes read, negative error value otherwise */ static int vtpm_proxy_tpm_op_recv(struct tpm_chip *chip, u8 *buf, size_t count) { … } static int vtpm_proxy_is_driver_command(struct tpm_chip *chip, u8 *buf, size_t count) { … } /* * Called when core TPM driver forwards TPM requests to 'server side'. * * @chip: tpm chip to use * @buf: send buffer * @count: bytes to send * * Return: * 0 in case of success, negative error value otherwise. */ static int vtpm_proxy_tpm_op_send(struct tpm_chip *chip, u8 *buf, size_t count) { … } static void vtpm_proxy_tpm_op_cancel(struct tpm_chip *chip) { … } static u8 vtpm_proxy_tpm_op_status(struct tpm_chip *chip) { … } static bool vtpm_proxy_tpm_req_canceled(struct tpm_chip *chip, u8 status) { … } static int vtpm_proxy_request_locality(struct tpm_chip *chip, int locality) { … } static const struct tpm_class_ops vtpm_proxy_tpm_ops = …; /* * Code related to the startup of the TPM 2 and startup of TPM 1.2 + * retrieval of timeouts and durations. */ static void vtpm_proxy_work(struct work_struct *work) { … } /* * vtpm_proxy_work_stop: make sure the work has finished * * This function is useful when user space closed the fd * while the driver still determines timeouts. */ static void vtpm_proxy_work_stop(struct proxy_dev *proxy_dev) { … } /* * vtpm_proxy_work_start: Schedule the work for TPM 1.2 & 2 initialization */ static inline void vtpm_proxy_work_start(struct proxy_dev *proxy_dev) { … } /* * Code related to creation and deletion of device pairs */ static struct proxy_dev *vtpm_proxy_create_proxy_dev(void) { … } /* * Undo what has been done in vtpm_create_proxy_dev */ static inline void vtpm_proxy_delete_proxy_dev(struct proxy_dev *proxy_dev) { … } /* * Create a /dev/tpm%d and 'server side' file descriptor pair * * Return: * Returns file pointer on success, an error value otherwise */ static struct file *vtpm_proxy_create_device( struct vtpm_proxy_new_dev *vtpm_new_dev) { … } /* * Counter part to vtpm_create_device. */ static void vtpm_proxy_delete_device(struct proxy_dev *proxy_dev) { … } /* * Code related to the control device /dev/vtpmx */ /** * vtpmx_ioc_new_dev - handler for the %VTPM_PROXY_IOC_NEW_DEV ioctl * @file: /dev/vtpmx * @ioctl: the ioctl number * @arg: pointer to the struct vtpmx_proxy_new_dev * * Creates an anonymous file that is used by the process acting as a TPM to * communicate with the client processes. The function will also add a new TPM * device through which data is proxied to this TPM acting process. The caller * will be provided with a file descriptor to communicate with the clients and * major and minor numbers for the TPM device. */ static long vtpmx_ioc_new_dev(struct file *file, unsigned int ioctl, unsigned long arg) { … } /* * vtpmx_fops_ioctl: ioctl on /dev/vtpmx * * Return: * Returns 0 on success, a negative error code otherwise. */ static long vtpmx_fops_ioctl(struct file *f, unsigned int ioctl, unsigned long arg) { … } static const struct file_operations vtpmx_fops = …; static struct miscdevice vtpmx_miscdev = …; static int __init vtpm_module_init(void) { … } static void __exit vtpm_module_exit(void) { … } module_init(…) …; module_exit(vtpm_module_exit); MODULE_AUTHOR(…) …; MODULE_DESCRIPTION(…) …; MODULE_VERSION(…) …; MODULE_LICENSE(…) …;