mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-06 05:04:26 +00:00
159 lines
2.7 KiB
C
159 lines
2.7 KiB
C
|
/*
|
||
|
* (C) Copyright 2016
|
||
|
* Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
|
||
|
*
|
||
|
* SPDX-License-Identifier: GPL-2.0+
|
||
|
*/
|
||
|
|
||
|
#include <common.h>
|
||
|
#include <tpm.h>
|
||
|
#include <malloc.h>
|
||
|
#include <linux/ctype.h>
|
||
|
#include <asm/unaligned.h>
|
||
|
|
||
|
#include "hre.h"
|
||
|
|
||
|
int flush_keys(void)
|
||
|
{
|
||
|
u16 key_count;
|
||
|
u8 buf[288];
|
||
|
u8 *ptr;
|
||
|
u32 err;
|
||
|
uint i;
|
||
|
|
||
|
/* fetch list of already loaded keys in the TPM */
|
||
|
err = tpm_get_capability(TPM_CAP_HANDLE, TPM_RT_KEY, buf, sizeof(buf));
|
||
|
if (err)
|
||
|
return -1;
|
||
|
key_count = get_unaligned_be16(buf);
|
||
|
ptr = buf + 2;
|
||
|
for (i = 0; i < key_count; ++i, ptr += 4) {
|
||
|
err = tpm_flush_specific(get_unaligned_be32(ptr), TPM_RT_KEY);
|
||
|
if (err && err != TPM_KEY_OWNER_CONTROL)
|
||
|
return err;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int decode_hexstr(char *hexstr, u8 **result)
|
||
|
{
|
||
|
int len = strlen(hexstr);
|
||
|
int bytes = len / 2;
|
||
|
int i;
|
||
|
u8 acc = 0;
|
||
|
|
||
|
if (len % 2 == 1)
|
||
|
return 1;
|
||
|
|
||
|
*result = (u8 *)malloc(bytes);
|
||
|
|
||
|
for (i = 0; i < len; i++) {
|
||
|
char cur = tolower(hexstr[i]);
|
||
|
u8 val;
|
||
|
|
||
|
if ((cur >= 'a' && cur <= 'f') || (cur >= '0' && cur <= '9')) {
|
||
|
val = cur - (cur > '9' ? 87 : 48);
|
||
|
|
||
|
if (i % 2 == 0)
|
||
|
acc = 16 * val;
|
||
|
else
|
||
|
(*result)[i / 2] = acc + val;
|
||
|
} else {
|
||
|
free(*result);
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int extract_subprogram(u8 **progdata, u32 expected_magic,
|
||
|
struct key_program **result)
|
||
|
{
|
||
|
struct key_program *prog = *result;
|
||
|
u32 magic, code_crc, code_size;
|
||
|
|
||
|
magic = get_unaligned_be32(*progdata);
|
||
|
code_crc = get_unaligned_be32(*progdata + 4);
|
||
|
code_size = get_unaligned_be32(*progdata + 8);
|
||
|
|
||
|
*progdata += 12;
|
||
|
|
||
|
if (magic != expected_magic)
|
||
|
return -1;
|
||
|
|
||
|
*result = malloc(sizeof(struct key_program) + code_size);
|
||
|
|
||
|
if (!*result)
|
||
|
return -1;
|
||
|
|
||
|
prog->magic = magic;
|
||
|
prog->code_crc = code_crc;
|
||
|
prog->code_size = code_size;
|
||
|
memcpy(prog->code, *progdata, code_size);
|
||
|
|
||
|
*progdata += code_size;
|
||
|
|
||
|
if (hre_verify_program(prog)) {
|
||
|
free(prog);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
struct key_program *parse_and_check_keyprog(u8 *progdata)
|
||
|
{
|
||
|
struct key_program *result = NULL, *hmac = NULL;
|
||
|
|
||
|
/* Part 1: Load key program */
|
||
|
|
||
|
if (extract_subprogram(&progdata, MAGIC_KEY_PROGRAM, &result))
|
||
|
return NULL;
|
||
|
|
||
|
/* Part 2: Load hmac program */
|
||
|
|
||
|
if (extract_subprogram(&progdata, MAGIC_HMAC, &hmac))
|
||
|
return NULL;
|
||
|
|
||
|
free(hmac);
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
int load_and_run_keyprog(void)
|
||
|
{
|
||
|
char *cmd = NULL;
|
||
|
u8 *binprog = NULL;
|
||
|
char *hexprog;
|
||
|
struct key_program *prog;
|
||
|
|
||
|
cmd = getenv("loadkeyprogram");
|
||
|
|
||
|
if (!cmd || run_command(cmd, 0))
|
||
|
return 1;
|
||
|
|
||
|
hexprog = getenv("keyprogram");
|
||
|
|
||
|
if (decode_hexstr(hexprog, &binprog))
|
||
|
return 1;
|
||
|
|
||
|
prog = parse_and_check_keyprog(binprog);
|
||
|
free(binprog);
|
||
|
|
||
|
if (!prog)
|
||
|
return 1;
|
||
|
|
||
|
if (hre_run_program(prog->code, prog->code_size)) {
|
||
|
free(prog);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
printf("\nSD code ran successfully\n");
|
||
|
|
||
|
free(prog);
|
||
|
|
||
|
return 0;
|
||
|
}
|