⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tpm_tis.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * tpm_tis.c - QEMU emulator for a 1.2 TPM with TIS interface * * Copyright (C) 2006 IBM Corporation * * Author: Stefan Berger <stefanb@us.ibm.com> *         David Safford <safford@us.ibm.com> * * 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. * * * Implementation of the TIS interface according to specs at * https://www.trustedcomputinggroup.org/groups/pc_client/TCG_PCClientTPMSpecification_1-20_1-00_FINAL.pdf * */#include <sys/types.h>#include <sys/stat.h>#include <sys/socket.h>#include <sys/un.h>#include <fcntl.h>#include <errno.h>#include "vl.h"//#define DEBUG_TPM#define TPM_MAX_PKT	              4096#define VTPM_BAD_INSTANCE             (uint32_t)0xffffffff#define TIS_ADDR_BASE                 0xFED40000/* tis registers */#define TPM_REG_ACCESS                0x00#define TPM_REG_INT_ENABLE            0x08#define TPM_REG_INT_VECTOR            0x0c#define TPM_REG_INT_STATUS            0x10#define TPM_REG_INTF_CAPABILITY       0x14#define TPM_REG_STS                   0x18#define TPM_REG_DATA_FIFO             0x24#define TPM_REG_DID_VID               0xf00#define TPM_REG_RID                   0xf04#define STS_VALID                    (1 << 7)#define STS_COMMAND_READY            (1 << 6)#define STS_TPM_GO                   (1 << 5)#define STS_DATA_AVAILABLE           (1 << 4)#define STS_EXPECT                   (1 << 3)#define STS_RESPONSE_RETRY           (1 << 1)#define ACCESS_TPM_REG_VALID_STS     (1 << 7)#define ACCESS_ACTIVE_LOCALITY       (1 << 5)#define ACCESS_BEEN_SEIZED           (1 << 4)#define ACCESS_SEIZE                 (1 << 3)#define ACCESS_PENDING_REQUEST       (1 << 2)#define ACCESS_REQUEST_USE           (1 << 1)#define ACCESS_TPM_ESTABLISHMENT     (1 << 0)#define INT_ENABLED                  (1 << 31)#define INT_DATA_AVAILABLE           (1 << 0)#define INT_LOCALITY_CHANGED         (1 << 2)#define INT_COMMAND_READY            (1 << 7)#define INTERRUPTS_SUPPORTED         (INT_LOCALITY_CHANGED | \                                      INT_DATA_AVAILABLE   | \                                      INT_COMMAND_READY)#define CAPABILITIES_SUPPORTED       ((1 << 4) |            \                                      INTERRUPTS_SUPPORTED)enum {  STATE_IDLE = 0,  STATE_READY,  STATE_COMPLETION,  STATE_EXECUTION,  STATE_RECEPTION};#define NUM_LOCALITIES   5#define NO_LOCALITY      0xff#define IS_VALID_LOC(x) ((x) < NUM_LOCALITIES)#define TPM_DID          0x0001#define TPM_VID          0x0001#define TPM_RID          0x0001/* if the connection to the vTPM should be closed after a successfully   received response; set to '0' to allow keeping the connection */#define FORCE_CLOSE      0/* local data structures */typedef struct TPMTx {    int fd[2];} tpmTx;typedef struct TPMBuffer {    uint8_t instance[4];      /* instance number in network byte order */    uint8_t buf[TPM_MAX_PKT];} __attribute__((packed)) tpmBuffer;/* locality data */typedef struct TPMLocal {    uint32_t state;    uint8_t access;    uint8_t sts;    uint32_t inte;    uint32_t ints;} tpmLoc;/* overall state of the TPM interface; 's' marks as save upon suspension */typedef struct TPMState {    uint32_t offset;            /* s */    tpmBuffer buffer;           /* s */    uint8_t active_loc;         /* s */    uint8_t aborting_locty;    uint8_t next_locty;    uint8_t irq_pending;        /* s */    tpmLoc loc[NUM_LOCALITIES]; /* s */    QEMUTimer *poll_timer;    SetIRQFunc *set_irq;    void *irq_opaque;    int irq;    int poll_attempts;    uint32_t vtpm_instance;  /* vtpm inst. number; determined from xenstore*/    int Transmitlayer;    tpmTx tpmTx;} tpmState;/* local prototypes */static int TPM_Send(tpmState *s, tpmBuffer *buffer, uint8_t locty, char *msg);static int TPM_Receive(tpmState *s, tpmBuffer *buffer);static uint32_t vtpm_instance_from_xenstore(void);static void tis_poll_timer(void *opaque);static void tis_prep_next_interrupt(tpmState *s);static void tis_raise_irq(tpmState *s, uint8_t locty, uint32_t irqmask);static void close_vtpm_channel(tpmState *s, int force);static void open_vtpm_channel(tpmState *s);static void tis_attempt_receive(tpmState *s, uint8_t locty);/* transport layer functions: local sockets */static int create_local_socket(tpmState *s, uint32_t vtpm_instance);static int write_local_socket(tpmState *s, const tpmBuffer *);static int read_local_socket(tpmState *s, tpmBuffer *);static int close_local_socket(tpmState *s, int force);static int has_channel_local_socket(tpmState *s);#define LOCAL_SOCKET_PATH     "/var/vtpm/socks/%d.socket" #define NUM_TRANSPORTS 1struct vTPM_transmit {    int (*open_fn) (tpmState *s, uint32_t vtpm_instance);    int (*write_fn) (tpmState *s, const tpmBuffer *);    int (*read_fn) (tpmState *s, tpmBuffer *);    int (*close_fn) (tpmState *s, int);    int (*has_channel) (tpmState *s);} vTPMTransmit[NUM_TRANSPORTS] = {    { .open_fn = create_local_socket,      .write_fn = write_local_socket,      .read_fn = read_local_socket,      .close_fn = close_local_socket,      .has_channel = has_channel_local_socket,    }};#define IS_COMM_WITH_VTPM(s)                            \     ((s)->Transmitlayer >= 0 &&                        \      vTPMTransmit[(s)->Transmitlayer].has_channel(s))/********************************************************************** helper functions *********************************************************************/static inline uint32_t tpm_get_size_from_buffer(const uint8_t *buffer){    uint32_t len = (buffer[4] << 8) + buffer[5];    return len;}static inline void tpm_initialize_instance(tpmState *s, uint32_t instance){    s->buffer.instance[0] = (instance >> 24) & 0xff;    s->buffer.instance[1] = (instance >> 16) & 0xff;    s->buffer.instance[2] = (instance >>  8) & 0xff;    s->buffer.instance[3] = (instance >>  0) & 0xff;}/* * open communication channel with a vTPM */static void open_vtpm_channel(tpmState *s){    int idx;    /* search a usable transmit layer */    for (idx = 0; idx < NUM_TRANSPORTS; idx++) {        if (1 == vTPMTransmit[idx].open_fn(s, s->vtpm_instance)) {            /* found one */            s->Transmitlayer = idx;            break;        }    }}/* * close the communication channel with the vTPM */static inline void close_vtpm_channel(tpmState *s, int force){    if (1 == vTPMTransmit[s->Transmitlayer].close_fn(s, force)) {        s->Transmitlayer = -1;    }}static inline uint8_t locality_from_addr(target_phys_addr_t addr){    return (uint8_t)((addr >> 12) & 0x7);}/**********************************************************************    low-level transmission layer methods *********************************************************************//* * the 'open' method that creates the filedescriptor for communicating * only one is needed for reading and writing */static int create_local_socket(tpmState *s, uint32_t vtpm_instance){    int success = 1;    if (s->tpmTx.fd[0] < 0) {        s->tpmTx.fd[0] = socket(PF_LOCAL, SOCK_STREAM, 0);#ifdef DEBUG_TPM        fprintf(logfile," SOCKET FD %d errno %d \n",  s->tpmTx.fd[0], errno );#endif        if (has_channel_local_socket(s)) {            int ret;             struct sockaddr_un addr;            memset(&addr, 0x0, sizeof(addr));            addr.sun_family = AF_LOCAL;            snprintf(addr.sun_path, sizeof(addr.sun_path)-1,		     LOCAL_SOCKET_PATH, (uint32_t) vtpm_instance);#ifdef DEBUG_TPM	    fprintf(logfile," SOCKET NAME %s \n",  addr.sun_path );#endif            if ((ret = connect(s->tpmTx.fd[0], (struct sockaddr *)&addr,			       sizeof(addr))) != 0) {                close_local_socket(s, 1);#ifdef DEBUG_TPM		fprintf(logfile," RET %d  errno %d\n", ret, errno );#endif                success = 0;            } else {                /* put filedescriptor in non-blocking mode for polling */#ifdef DEBUG_TPM	      fprintf(logfile," put filedescriptor in non-blocking mode "		      "for polling \n");#endif                int flags = fcntl(s->tpmTx.fd[0], F_GETFL);                fcntl(s->tpmTx.fd[0], F_SETFL, flags | O_NONBLOCK);            }#ifdef DEBUG_TPM            if (success)                fprintf(logfile," Successfully connected using local socket"                                "%s.\n",addr.sun_path);            else                fprintf(logfile," Could not connect to local socket "                                "%s.\n",addr.sun_path);#endif        } else {            success = 0;        }    }    return success;}/* * the 'write' method for sending requests to the vTPM * four bytes with the vTPM instance number are prepended to each request * the locality in which the command was sent is transmitted in the * highest 3 bits */static int write_local_socket(tpmState *s, const tpmBuffer *buffer){    uint32_t size = tpm_get_size_from_buffer(buffer->buf);    int len;    len = write(s->tpmTx.fd[0],                buffer->instance,                sizeof(buffer->instance) + size);    if (len == sizeof(buffer->instance) + size) {        return len;    } else {        return -1;    }}/* * the 'read' method for receiving of responses from the TPM * this function expects that four bytes with the instance number * are received from the vTPM */static int read_local_socket(tpmState *s, tpmBuffer *buffer){    int off;#ifdef DEBUG_TPM    fprintf(logfile, "Reading from fd %d\n", s->tpmTx.fd[0]);#endif    off = read(s->tpmTx.fd[0],               buffer->instance,               sizeof(buffer->instance)+TPM_MAX_PKT);#ifdef DEBUG_TPM    fprintf(logfile, "Read %d bytes\n", off);#endif    return off;}/* * the 'close' method * shut down communication with the vTPM * 'force' = 1 indicates that the socket *must* be closed * 'force' = 0 indicates that a connection may be maintained */static int close_local_socket(tpmState *s, int force){    if (force) {        close(s->tpmTx.fd[0]);#ifdef DEBUG_TPM        fprintf(logfile,"Closed connection with fd %d\n",s->tpmTx.fd[0]);#endif        s->tpmTx.fd[0] = -1;        return 1; /* socket was closed */    }#ifdef DEBUG_TPM    fprintf(logfile,"Keeping connection with fd %d\n",s->tpmTx.fd[0]);#endif    return 0;}/* * the 'has_channel' method that checks whether there's a communication * channel with the vTPM */static int has_channel_local_socket(tpmState *s){    return (s->tpmTx.fd[0] > 0);}/**********************************************************************//* * read a byte of response data */static uint32_t tpm_data_read(tpmState *s, uint8_t locty){    uint32_t ret, len;    /* try to receive data, if none are there it is ok */    tis_attempt_receive(s, locty);    if (s->loc[locty].state != STATE_COMPLETION) {        return 0xff;    }    len = tpm_get_size_from_buffer(s->buffer.buf);    ret = s->buffer.buf[s->offset++];    if (s->offset >= len) {        s->loc[locty].sts = STS_VALID ;        s->offset = 0;    }#ifdef DEBUG_TPM    fprintf(logfile,"tpm_data_read byte x%02x   [%d]\n",ret,s->offset-1);#endif    return ret;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -