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