1198160Srrs// SPDX-License-Identifier: GPL-2.0+ 2198160Srrs/* 3198160Srrs * (C) Copyright 2016 4198160Srrs * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc 5198160Srrs */ 6198160Srrs 7198160Srrs#include <common.h> 8198160Srrs#include <command.h> 9198160Srrs#include <env.h> 10198160Srrs#include <tpm-v1.h> 11198160Srrs#include <malloc.h> 12198160Srrs#include <linux/ctype.h> 13198160Srrs#include <asm/unaligned.h> 14198160Srrs 15#include "hre.h" 16 17int flush_keys(struct udevice *tpm) 18{ 19 u16 key_count; 20 u8 buf[288]; 21 u8 *ptr; 22 u32 err; 23 uint i; 24 25 /* fetch list of already loaded keys in the TPM */ 26 err = tpm1_get_capability(tpm, TPM_CAP_HANDLE, TPM_RT_KEY, buf, 27 sizeof(buf)); 28 if (err) 29 return -1; 30 key_count = get_unaligned_be16(buf); 31 ptr = buf + 2; 32 for (i = 0; i < key_count; ++i, ptr += 4) { 33 err = tpm1_flush_specific(tpm, get_unaligned_be32(ptr), 34 TPM_RT_KEY); 35 if (err && err != TPM_KEY_OWNER_CONTROL) 36 return err; 37 } 38 39 return 0; 40} 41 42int decode_hexstr(char *hexstr, u8 **result) 43{ 44 int len = strlen(hexstr); 45 int bytes = len / 2; 46 int i; 47 u8 acc = 0; 48 49 if (len % 2 == 1) 50 return 1; 51 52 *result = (u8 *)malloc(bytes); 53 54 for (i = 0; i < len; i++) { 55 char cur = tolower(hexstr[i]); 56 u8 val; 57 58 if ((cur >= 'a' && cur <= 'f') || (cur >= '0' && cur <= '9')) { 59 val = cur - (cur > '9' ? 87 : 48); 60 61 if (i % 2 == 0) 62 acc = 16 * val; 63 else 64 (*result)[i / 2] = acc + val; 65 } else { 66 free(*result); 67 return 1; 68 } 69 } 70 71 return 0; 72} 73 74int extract_subprogram(u8 **progdata, u32 expected_magic, 75 struct key_program **result) 76{ 77 struct key_program *prog = *result; 78 u32 magic, code_crc, code_size; 79 80 magic = get_unaligned_be32(*progdata); 81 code_crc = get_unaligned_be32(*progdata + 4); 82 code_size = get_unaligned_be32(*progdata + 8); 83 84 *progdata += 12; 85 86 if (magic != expected_magic) 87 return -1; 88 89 *result = malloc(sizeof(struct key_program) + code_size); 90 91 if (!*result) 92 return -1; 93 94 prog->magic = magic; 95 prog->code_crc = code_crc; 96 prog->code_size = code_size; 97 memcpy(prog->code, *progdata, code_size); 98 99 *progdata += code_size; 100 101 if (hre_verify_program(prog)) { 102 free(prog); 103 return -1; 104 } 105 106 return 0; 107} 108 109struct key_program *parse_and_check_keyprog(u8 *progdata) 110{ 111 struct key_program *result = NULL, *hmac = NULL; 112 113 /* Part 1: Load key program */ 114 115 if (extract_subprogram(&progdata, MAGIC_KEY_PROGRAM, &result)) 116 return NULL; 117 118 /* Part 2: Load hmac program */ 119 120 if (extract_subprogram(&progdata, MAGIC_HMAC, &hmac)) 121 return NULL; 122 123 free(hmac); 124 125 return result; 126} 127 128int load_and_run_keyprog(struct udevice *tpm) 129{ 130 char *cmd = NULL; 131 u8 *binprog = NULL; 132 char *hexprog; 133 struct key_program *prog; 134 135 cmd = env_get("loadkeyprogram"); 136 137 if (!cmd || run_command(cmd, 0)) 138 return 1; 139 140 hexprog = env_get("keyprogram"); 141 142 if (decode_hexstr(hexprog, &binprog)) 143 return 1; 144 145 prog = parse_and_check_keyprog(binprog); 146 free(binprog); 147 148 if (!prog) 149 return 1; 150 151 if (hre_run_program(tpm, prog->code, prog->code_size)) { 152 free(prog); 153 return 1; 154 } 155 156 printf("\nSD code ran successfully\n"); 157 158 free(prog); 159 160 return 0; 161} 162