/* * Copyright (C) 2019 Intel Corporation * All rights reserved. * * 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 in * this position and unchanged. * 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 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 AUTHOR 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 #include #include #include #include #include #include #include #include #include #include "att_keybox.h" #include "log.h" static const uuid_le HECI_CLIENT_GUID = UUID_LE(0x8e6a6715, 0x9abc, 0x4043, 0x88, 0xef, 0x9e, 0x39, 0xc6, 0xf6, 0x3e, 0x0f); #define MEI_DEV "/dev/mei0" #define HECI_READ_ATTKB_GRP_ID 0x0a #define HECI_READ_ATTKB_EX_CMD_REQ 0x1a #define HECI_MTU 2048 uint16_t get_attkb_size(void) { struct mei_connect_client_data mdcd; int fd = -1, ret = 0; HECI_READ_ATTKB_EX_Request req; HECI_READ_ATTKB_EX_Response resp; fd = open(MEI_DEV, O_RDWR); if (fd == -1) { pr_err("Failed to open %s, %s\n", MEI_DEV, strerror(errno)); return 0; } memset(&mdcd, 0, sizeof(mdcd)); memcpy(&mdcd.in_client_uuid, &HECI_CLIENT_GUID, sizeof(HECI_CLIENT_GUID)); ret = ioctl(fd, IOCTL_MEI_CONNECT_CLIENT, &mdcd); if (ret) { pr_err("HECI connection failed, %s\n", strerror(errno)); goto err; } /* Get the size of encrypted attestation keybox */ memset(&req, 0, sizeof(req)); req.header.groupid = HECI_READ_ATTKB_GRP_ID; req.header.command = HECI_READ_ATTKB_EX_CMD_REQ; req.size = 0; req.offset = 0; req.flags.encryption = 1; ret = write(fd, &req, sizeof(req)); if (ret != sizeof(req)) { pr_err("Failed to send HECI command, %s\n", strerror(errno)); goto err; } ret = read(fd, &resp, sizeof(resp)); if (ret != sizeof(resp)) { pr_err("ret = %d,Failed to read HECI command result, %d:%s\n", ret, errno, strerror(errno)); goto err; } if ((resp.header.is_response != 1) || (resp.header.result != 0)) { pr_err("Failed to check resp header = 0x%x\n", resp.header.result); goto err; } if (resp.total_file_size == 0) { pr_err("ret = %d, Unexpected filesize 0!\n", ret); } close(fd); return resp.total_file_size; err: close(fd); return 0; } uint16_t read_attkb(void *data, uint16_t size) { struct mei_connect_client_data mdcd; HECI_READ_ATTKB_EX_Request req; HECI_READ_ATTKB_EX_Response resp; int fd = -1, ret = 0; uint16_t left_size = 0; uint16_t bytes_read = 0; void *ptr = data; if ((ptr == NULL) || (size == 0)) { return 0; } fd = open(MEI_DEV, O_RDWR); if (fd == -1) { pr_err("Failed to open %s, %s\n", MEI_DEV, strerror(errno)); return 0; } memset(&mdcd, 0, sizeof(mdcd)); memcpy(&mdcd.in_client_uuid, &HECI_CLIENT_GUID, sizeof(HECI_CLIENT_GUID)); ret = ioctl(fd, IOCTL_MEI_CONNECT_CLIENT, &mdcd); if (ret) { pr_err("HECI connection failed, %s\n", strerror(errno)); goto err; } left_size = size; memset(&req, 0, sizeof(req)); req.header.groupid = HECI_READ_ATTKB_GRP_ID; req.header.command = HECI_READ_ATTKB_EX_CMD_REQ; req.offset = 0; req.size = HECI_MTU > left_size ? left_size : HECI_MTU; req.flags.encryption = 1; while (left_size) { req.offset = bytes_read; req.size = HECI_MTU > left_size ? left_size : HECI_MTU; ret = write(fd, &req, sizeof(req)); if (ret != sizeof(req)) { pr_err("Failed to send HECI command, %s\n", strerror(errno)); goto err; } ret = read(fd, &resp, sizeof(resp)); if (ret != sizeof(resp)) { pr_err("Failed to read HECI command result, %s\n", strerror(errno)); goto err; } if ((resp.header.is_response != 1) || (resp.header.result != 0)) { pr_err("Failed to check resp header = 0x%x\n", resp.header.result); goto err; } ret = read(fd, (uint8_t *)data + bytes_read, req.size); if (ret != req.size) { pr_err("Failed to read attkb, %s\n", strerror(errno)); goto err; } ptr += ret; bytes_read += ret; left_size -= ret; } close(fd); return bytes_read; err: close(fd); return 0; }