mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-25 15:02:13 +00:00
DM: Attestation Keybox support in SOS DM
Retrieve the encrypted attestation Keybox from CSE and provision it to RPMB storage. Tracked-On: #2625 Signed-off-by: Huang Yang <yang.huang@intel.com> Signed-off-by: Wei Xinghai <xinghaix.wei@intel.com> Signed-off-by: Chen Gang <gang.g.chen@intel.com> Acked-by: Zhu Bing <bing.zhu@intel.com>
This commit is contained in:
parent
0066171468
commit
1a59fa26fe
@ -83,6 +83,7 @@ SRCS += hw/platform/acpi/acpi.c
|
|||||||
SRCS += hw/platform/acpi/acpi_pm.c
|
SRCS += hw/platform/acpi/acpi_pm.c
|
||||||
SRCS += hw/platform/rpmb/rpmb_sim.c
|
SRCS += hw/platform/rpmb/rpmb_sim.c
|
||||||
SRCS += hw/platform/rpmb/rpmb_backend.c
|
SRCS += hw/platform/rpmb/rpmb_backend.c
|
||||||
|
SRCS += hw/platform/rpmb/att_keybox.c
|
||||||
SRCS += hw/platform/debugexit.c
|
SRCS += hw/platform/debugexit.c
|
||||||
SRCS += hw/pci/wdt_i6300esb.c
|
SRCS += hw/pci/wdt_i6300esb.c
|
||||||
SRCS += hw/pci/lpc.c
|
SRCS += hw/pci/lpc.c
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
#include <errno.h>
|
||||||
#include "dm.h"
|
#include "dm.h"
|
||||||
#include "pci_core.h"
|
#include "pci_core.h"
|
||||||
#include "virtio.h"
|
#include "virtio.h"
|
||||||
@ -52,10 +52,15 @@
|
|||||||
#include "rpmb.h"
|
#include "rpmb.h"
|
||||||
#include "rpmb_sim.h"
|
#include "rpmb_sim.h"
|
||||||
#include "rpmb_backend.h"
|
#include "rpmb_backend.h"
|
||||||
|
#include "att_keybox.h"
|
||||||
|
|
||||||
#define VIRTIO_RPMB_RINGSZ 64
|
#define VIRTIO_RPMB_RINGSZ 64
|
||||||
#define VIRTIO_RPMB_MAXSEGS 5
|
#define VIRTIO_RPMB_MAXSEGS 5
|
||||||
#define ADDR_NOT_PRESENT -2
|
#define ERROR_ADDRESS_OUT_OF_RANGE -2
|
||||||
|
#define BLOCK_BARA_BASE_ADDRESS 1
|
||||||
|
#define BLOCK_BARA_SIGNATURE "BARA"
|
||||||
|
#define SIGNATURE_LENGTH (sizeof(BLOCK_BARA_SIGNATURE) - 1)
|
||||||
|
#define ATTKB_PRESENT_FLAG_BIT 0x1
|
||||||
|
|
||||||
static const char PHYSICAL_RPMB_STR[] = "physical_rpmb";
|
static const char PHYSICAL_RPMB_STR[] = "physical_rpmb";
|
||||||
static int virtio_rpmb_debug = 1;
|
static int virtio_rpmb_debug = 1;
|
||||||
@ -130,14 +135,14 @@ rpmb_check_response(const char *cmd_str, enum rpmb_response response_type,
|
|||||||
for (i = 0; i < frame_cnt; i++) {
|
for (i = 0; i < frame_cnt; i++) {
|
||||||
if (swap16(frames[i].req_resp) != response_type) {
|
if (swap16(frames[i].req_resp) != response_type) {
|
||||||
DPRINTF(("%s: Bad response type, 0x%x, expected 0x%x\n",
|
DPRINTF(("%s: Bad response type, 0x%x, expected 0x%x\n",
|
||||||
cmd_str, swap16(frames[i].req_resp), response_type));
|
cmd_str, swap16(frames[i].req_resp), response_type));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (swap16(frames[i].result) != RPMB_RES_OK) {
|
if (swap16(frames[i].result) != RPMB_RES_OK) {
|
||||||
if (swap16(frames[i].result) == RPMB_RES_ADDR_FAILURE) {
|
if (swap16(frames[i].result) == RPMB_RES_ADDR_FAILURE) {
|
||||||
DPRINTF(("%s: Addr failure, %u\n", cmd_str, swap16(frames[i].addr)));
|
DPRINTF(("%s: Addr failure, %u\n", cmd_str, swap16(frames[i].addr)));
|
||||||
return ADDR_NOT_PRESENT;
|
return ERROR_ADDRESS_OUT_OF_RANGE;
|
||||||
}
|
}
|
||||||
DPRINTF(("%s: Bad result, 0x%x\n", cmd_str, swap16(frames[i].result)));
|
DPRINTF(("%s: Bad result, 0x%x\n", cmd_str, swap16(frames[i].result)));
|
||||||
return -1;
|
return -1;
|
||||||
@ -198,19 +203,14 @@ rpmb_get_counter(__u8 mode, __u8 *key, __u32 *counter, __u16 *result)
|
|||||||
iseq.h.num_of_cmds = 2;
|
iseq.h.num_of_cmds = 2;
|
||||||
|
|
||||||
if (mode == RPMB_PHY_MODE) {
|
if (mode == RPMB_PHY_MODE) {
|
||||||
/* open rpmb device.*/
|
|
||||||
fd = open(RPMB_PHY_PATH_NAME, O_RDWR | O_NONBLOCK);
|
fd = open(RPMB_PHY_PATH_NAME, O_RDWR | O_NONBLOCK);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
DPRINTF(("failed to open %s.\n", RPMB_PHY_PATH_NAME));
|
DPRINTF(("failed to open %s.\n", RPMB_PHY_PATH_NAME));
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* send ioctl cmd.*/
|
|
||||||
rc = ioctl(fd, RPMB_IOC_SEQ_CMD, &iseq);
|
rc = ioctl(fd, RPMB_IOC_SEQ_CMD, &iseq);
|
||||||
|
|
||||||
/* close rpmb device.*/
|
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
if (rc) {
|
if (rc) {
|
||||||
DPRINTF(("get counter for physical rpmb failed.\n"));
|
DPRINTF(("get counter for physical rpmb failed.\n"));
|
||||||
return rc;
|
return rc;
|
||||||
@ -229,10 +229,15 @@ rpmb_get_counter(__u8 mode, __u8 *key, __u32 *counter, __u16 *result)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = rpmb_check_mac(key, &frame_out, 1);
|
/*In PHY RPMB MODE, DM doesn't have real RPMB key,
|
||||||
if (rc) {
|
*so no necessary to check the mac in the response.
|
||||||
DPRINTF(("rpmb counter check mac failed.\n"));
|
*/
|
||||||
return rc;
|
if (mode != RPMB_PHY_MODE) {
|
||||||
|
rc = rpmb_check_mac(key, &frame_out, 1);
|
||||||
|
if (rc) {
|
||||||
|
DPRINTF(("rpmb counter check mac failed.\n"));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*counter = swap32(frame_out.write_counter);
|
*counter = swap32(frame_out.write_counter);
|
||||||
@ -241,6 +246,90 @@ rpmb_get_counter(__u8 mode, __u8 *key, __u32 *counter, __u16 *result)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
rpmb_write_block(__u8 mode, __u8 *key, __u16 addr, void *buf, __u32 count)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
int fd;
|
||||||
|
__u32 i;
|
||||||
|
__u32 write_counter;
|
||||||
|
__u16 result;
|
||||||
|
struct {
|
||||||
|
struct rpmb_ioc_seq_cmd h;
|
||||||
|
struct rpmb_ioc_cmd cmd[3];
|
||||||
|
} iseq = {};
|
||||||
|
struct rpmb_frame frame_write;
|
||||||
|
struct rpmb_frame frame_rel[count];
|
||||||
|
struct rpmb_frame frame_read;
|
||||||
|
|
||||||
|
if (!buf || count == 0) {
|
||||||
|
DPRINTF(("%s:buf or count is invalid!\n", __func__));
|
||||||
|
return -ENOBUFS;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = rpmb_get_counter(mode, key, &write_counter, &result);
|
||||||
|
if (rc) {
|
||||||
|
DPRINTF(("%s: virtio_rpmb_get_counter failed\n", __func__));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
frame_write.addr = swap16(addr);
|
||||||
|
frame_write.req_resp = swap16(RPMB_REQ_RESULT_READ);
|
||||||
|
frame_write.write_counter = swap32(write_counter);
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
memset(&frame_rel[i], 0, sizeof(frame_rel[i]));
|
||||||
|
memcpy(frame_rel[i].data, buf + i * sizeof(frame_rel[i].data), sizeof(frame_rel[i].data));
|
||||||
|
frame_rel[i].write_counter = swap32(write_counter);
|
||||||
|
frame_rel[i].addr = swap16(addr);
|
||||||
|
frame_rel[i].block_count = swap16(count);
|
||||||
|
frame_rel[i].req_resp = swap16(RPMB_REQ_DATA_WRITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
iseq.cmd[0].flags = RPMB_F_WRITE | RPMB_F_REL_WRITE;
|
||||||
|
iseq.cmd[0].nframes = count;
|
||||||
|
iseq.cmd[0].frames_ptr = (__aligned_u64)(intptr_t)(frame_rel);
|
||||||
|
iseq.cmd[1].flags = RPMB_F_WRITE;
|
||||||
|
iseq.cmd[1].nframes = 1;
|
||||||
|
iseq.cmd[1].frames_ptr = (__aligned_u64)(intptr_t)(&frame_write);
|
||||||
|
iseq.cmd[2].flags = 0;
|
||||||
|
iseq.cmd[2].nframes = 1;
|
||||||
|
iseq.cmd[2].frames_ptr = (__aligned_u64)(intptr_t)(&frame_read);
|
||||||
|
iseq.h.num_of_cmds = 3;
|
||||||
|
|
||||||
|
if (mode == RPMB_PHY_MODE) {
|
||||||
|
fd = open(RPMB_PHY_PATH_NAME, O_RDWR | O_NONBLOCK);
|
||||||
|
if (fd < 0) {
|
||||||
|
DPRINTF(("failed to open %s for read blocks.\n", RPMB_PHY_PATH_NAME));
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ioctl(fd, RPMB_IOC_SEQ_CMD, &iseq);
|
||||||
|
close(fd);
|
||||||
|
if (rc) {
|
||||||
|
DPRINTF(("read blocks for physical rpmb failed.\n"));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*In PHY RPMB MODE, DM doesn't have real RPMB key,
|
||||||
|
*so no necessary to check the mac in the response.
|
||||||
|
*/
|
||||||
|
rc = rpmb_check_response("write blocks", RPMB_RESP_DATA_WRITE,
|
||||||
|
&frame_read, 1, NULL, NULL, &addr);
|
||||||
|
} else {
|
||||||
|
rc = rpmb_sim_send(&iseq);
|
||||||
|
if (rc) {
|
||||||
|
DPRINTF(("read blocks for simulated rpmb failed.\n"));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = rpmb_check_response("write blocks", RPMB_RESP_DATA_WRITE,
|
||||||
|
&frame_read, 1, key, NULL, &addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
rpmb_read_block(__u8 mode, __u8 *key, __u16 addr, void *buf, __u32 count)
|
rpmb_read_block(__u8 mode, __u8 *key, __u16 addr, void *buf, __u32 count)
|
||||||
{
|
{
|
||||||
@ -272,19 +361,14 @@ rpmb_read_block(__u8 mode, __u8 *key, __u16 addr, void *buf, __u32 count)
|
|||||||
iseq.h.num_of_cmds = 2;
|
iseq.h.num_of_cmds = 2;
|
||||||
|
|
||||||
if (mode == RPMB_PHY_MODE) {
|
if (mode == RPMB_PHY_MODE) {
|
||||||
/* open rpmb device.*/
|
|
||||||
fd = open(RPMB_PHY_PATH_NAME, O_RDWR | O_NONBLOCK);
|
fd = open(RPMB_PHY_PATH_NAME, O_RDWR | O_NONBLOCK);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
DPRINTF(("failed to open %s for read blocks.\n", RPMB_PHY_PATH_NAME));
|
DPRINTF(("failed to open %s for read blocks.\n", RPMB_PHY_PATH_NAME));
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* send ioctl cmd.*/
|
|
||||||
rc = ioctl(fd, RPMB_IOC_SEQ_CMD, &iseq);
|
rc = ioctl(fd, RPMB_IOC_SEQ_CMD, &iseq);
|
||||||
|
|
||||||
/* close rpmb device.*/
|
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
if (rc) {
|
if (rc) {
|
||||||
DPRINTF(("read blocks for physical rpmb failed.\n"));
|
DPRINTF(("read blocks for physical rpmb failed.\n"));
|
||||||
return rc;
|
return rc;
|
||||||
@ -335,7 +419,7 @@ rpmb_search_size(__u8 mode, __u8 *key, __u16 hint)
|
|||||||
case 0:
|
case 0:
|
||||||
low = curr + 1;
|
low = curr + 1;
|
||||||
break;
|
break;
|
||||||
case ADDR_NOT_PRESENT:
|
case ERROR_ADDRESS_OUT_OF_RANGE:
|
||||||
high = curr - 1;
|
high = curr - 1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -358,6 +442,116 @@ rpmb_get_blocks(void)
|
|||||||
return rpmb_block_count;
|
return rpmb_block_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
rpmb_read_bara(__u8 mode, __u8 *key, rpmb_block_t *block_table)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = rpmb_read_block(mode, key, BLOCK_BARA_BASE_ADDRESS, block_table, 1);
|
||||||
|
if (ret) {
|
||||||
|
DPRINTF(("rpmb read block table fail!\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rpmb_bara_init(rpmb_block_t *block_table, uint16_t size)
|
||||||
|
{
|
||||||
|
memcpy(block_table->signature, BLOCK_BARA_SIGNATURE, SIGNATURE_LENGTH);
|
||||||
|
block_table->length = RPMB_BLOCK_SIZE;
|
||||||
|
block_table->revision = 0;
|
||||||
|
block_table->flag |= ATTKB_PRESENT_FLAG_BIT;
|
||||||
|
block_table->attkb_addr = BLOCK_BARA_BASE_ADDRESS + 1;
|
||||||
|
block_table->attkb_size = size;
|
||||||
|
block_table->attkb_svn = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read RPMB BARA block from RPMB to check if AttKB exists or not.
|
||||||
|
* If does NOT exist, DM will send cmd to CSE via HECI to get AttKB size
|
||||||
|
* and AttKB. Both AttKB and BARA block will be written to specified RPMB address.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
rpmb_keybox_retrieve(__u8 mode, __u8 *key)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
uint32_t i;
|
||||||
|
uint32_t block_num;
|
||||||
|
rpmb_block_t *block_table;
|
||||||
|
uint8_t *attkb = NULL;
|
||||||
|
uint16_t kb_size;
|
||||||
|
uint32_t kb_buf_size = 0;
|
||||||
|
|
||||||
|
block_table = malloc(sizeof(rpmb_block_t));
|
||||||
|
if (!block_table) {
|
||||||
|
DPRINTF(("%s: block table malloc fail!\n", __func__));
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(block_table, 0, sizeof(rpmb_block_t));
|
||||||
|
/* read block table */
|
||||||
|
ret = rpmb_read_bara(mode, key, block_table);
|
||||||
|
if (ret) {
|
||||||
|
DPRINTF(("get block table fail!\n"));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memcmp(BLOCK_BARA_SIGNATURE, block_table->signature, SIGNATURE_LENGTH) || !(block_table->flag & ATTKB_PRESENT_FLAG_BIT)) {
|
||||||
|
kb_size = get_attkb_size();
|
||||||
|
if (kb_size == 0) {
|
||||||
|
DPRINTF(("rpmb get_attkb_size fail!\n"));
|
||||||
|
ret = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kb_size % RPMB_BLOCK_SIZE) {
|
||||||
|
kb_buf_size = (kb_size / RPMB_BLOCK_SIZE + 1) * RPMB_BLOCK_SIZE;
|
||||||
|
} else {
|
||||||
|
kb_buf_size = kb_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
attkb = (uint8_t *)malloc(kb_buf_size);
|
||||||
|
if (!attkb) {
|
||||||
|
DPRINTF(("%s: attkb malloc fail!\n", __func__));
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(attkb, 0, kb_buf_size);
|
||||||
|
ret = read_attkb(attkb, kb_size);
|
||||||
|
if (ret == 0) {
|
||||||
|
DPRINTF(("failed to read attkb"));
|
||||||
|
ret = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
rpmb_bara_init(block_table, kb_size);
|
||||||
|
block_num = (kb_size - 1) / RPMB_BLOCK_SIZE + 1;
|
||||||
|
for (i = 0; i < block_num; i++) {
|
||||||
|
ret = rpmb_write_block(mode, key, block_table->attkb_addr + i, attkb + i * RPMB_BLOCK_SIZE, 1);
|
||||||
|
if (ret) {
|
||||||
|
DPRINTF(("rpmb write key box fail!\n"));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = rpmb_write_block(mode, key, BLOCK_BARA_BASE_ADDRESS, block_table, 1);
|
||||||
|
if (ret) {
|
||||||
|
DPRINTF(("rpmb write block table fail!\n"));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (attkb) {
|
||||||
|
memset(attkb, 0, kb_buf_size);
|
||||||
|
free(attkb);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(block_table);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
virtio_rpmb_seq_handler(struct virtio_rpmb *rpmb, struct iovec *iov,
|
virtio_rpmb_seq_handler(struct virtio_rpmb *rpmb, struct iovec *iov,
|
||||||
int n, int *tlen)
|
int n, int *tlen)
|
||||||
@ -545,6 +739,10 @@ virtio_rpmb_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
|
|||||||
DPRINTF(("RPMB in physical mode!\n"));
|
DPRINTF(("RPMB in physical mode!\n"));
|
||||||
rpmb_mode_init(RPMB_PHY_MODE);
|
rpmb_mode_init(RPMB_PHY_MODE);
|
||||||
rpmb_block_count = rpmb_search_size(RPMB_PHY_MODE, key, 0);
|
rpmb_block_count = rpmb_search_size(RPMB_PHY_MODE, key, 0);
|
||||||
|
rc = rpmb_keybox_retrieve(RPMB_PHY_MODE, key);
|
||||||
|
if (rc < 0) {
|
||||||
|
DPRINTF(("rpmb_keybox_retrieve failed!\n"));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
DPRINTF(("RPMB in simulated mode!\n"));
|
DPRINTF(("RPMB in simulated mode!\n"));
|
||||||
rc = rpmb_sim_key_init(key);
|
rc = rpmb_sim_key_init(key);
|
||||||
|
197
devicemodel/hw/platform/rpmb/att_keybox.c
Normal file
197
devicemodel/hw/platform/rpmb/att_keybox.c
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
/*
|
||||||
|
* 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 <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <linux/mei.h>
|
||||||
|
#include "att_keybox.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) {
|
||||||
|
fprintf(stderr, "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) {
|
||||||
|
fprintf(stderr, "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)) {
|
||||||
|
fprintf(stderr, "Failed to send HECI command, %s\n",
|
||||||
|
strerror(errno));
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = read(fd, &resp, sizeof(resp));
|
||||||
|
if (ret != sizeof(resp)) {
|
||||||
|
fprintf(stderr, "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)) {
|
||||||
|
fprintf(stderr, "Failed to check resp header = 0x%x\n",
|
||||||
|
resp.header.result);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resp.total_file_size == 0) {
|
||||||
|
fprintf(stderr, "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) {
|
||||||
|
fprintf(stderr, "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) {
|
||||||
|
fprintf(stderr, "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)) {
|
||||||
|
fprintf(stderr, "Failed to send HECI command, %s\n",
|
||||||
|
strerror(errno));
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = read(fd, &resp, sizeof(resp));
|
||||||
|
if (ret != sizeof(resp)) {
|
||||||
|
fprintf(stderr, "Failed to read HECI command result, %s\n",
|
||||||
|
strerror(errno));
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((resp.header.is_response != 1) || (resp.header.result != 0)) {
|
||||||
|
fprintf(stderr, "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) {
|
||||||
|
fprintf(stderr, "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;
|
||||||
|
}
|
82
devicemodel/include/att_keybox.h
Normal file
82
devicemodel/include/att_keybox.h
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* 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:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * 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 COPYRIGHT HOLDERS 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
|
||||||
|
* COPYRIGHT OWNER 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _ATT_KEYBOX_H
|
||||||
|
#define _ATT_KEYBOX_H
|
||||||
|
|
||||||
|
typedef struct _HECI_MESSAGE_HEADER {
|
||||||
|
uint32_t groupid : 8;
|
||||||
|
uint32_t command : 7;
|
||||||
|
uint32_t is_response : 1;
|
||||||
|
uint32_t reserved : 8;
|
||||||
|
uint32_t result : 8;
|
||||||
|
} HECI_MESSAGE_HEADER;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
HECI_MESSAGE_HEADER header;
|
||||||
|
/* Size of the whole attkb file, including the added encryption header. */
|
||||||
|
uint16_t total_file_size;
|
||||||
|
uint16_t read_offset;
|
||||||
|
/* Size in bytes actually read */
|
||||||
|
uint16_t read_size;
|
||||||
|
uint16_t reserved;
|
||||||
|
uint8_t file_data[];
|
||||||
|
} HECI_READ_ATTKB_EX_Response;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
HECI_MESSAGE_HEADER header;
|
||||||
|
uint16_t offset; // Offset in file in bytes.
|
||||||
|
uint16_t size; // Size in bytes to read
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint32_t encryption : 1;
|
||||||
|
uint32_t reserved : 31;
|
||||||
|
} flags;
|
||||||
|
} HECI_READ_ATTKB_EX_Request;
|
||||||
|
|
||||||
|
#pragma pack (1)
|
||||||
|
typedef struct rpmb_block {
|
||||||
|
uint8_t signature[4];
|
||||||
|
uint32_t length;
|
||||||
|
uint32_t revision;
|
||||||
|
uint32_t flag;
|
||||||
|
uint16_t attkb_addr;
|
||||||
|
uint32_t attkb_size;
|
||||||
|
uint16_t attkb_svn;
|
||||||
|
uint16_t uos_rpmb_size;
|
||||||
|
uint8_t reserved[230];
|
||||||
|
} rpmb_block_t;
|
||||||
|
#pragma pack ()
|
||||||
|
|
||||||
|
uint16_t read_attkb(void *data, uint16_t size);
|
||||||
|
uint16_t get_attkb_size(void);
|
||||||
|
|
||||||
|
#endif // _ATT_KEYBOX_H
|
Loading…
Reference in New Issue
Block a user