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(void) 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_CAP_HANDLE, TPM_RT_KEY, buf, sizeof(buf)); 25 if (err) 26 return -1; 27 key_count = get_unaligned_be16(buf); 28 ptr = buf + 2; 29 for (i = 0; i < key_count; ++i, ptr += 4) { 30 err = tpm_flush_specific(get_unaligned_be32(ptr), TPM_RT_KEY); 31 if (err && err != TPM_KEY_OWNER_CONTROL) 32 return err; 33 } 34 35 return 0; 36 } 37 38 int decode_hexstr(char *hexstr, u8 **result) 39 { 40 int len = strlen(hexstr); 41 int bytes = len / 2; 42 int i; 43 u8 acc = 0; 44 45 if (len % 2 == 1) 46 return 1; 47 48 *result = (u8 *)malloc(bytes); 49 50 for (i = 0; i < len; i++) { 51 char cur = tolower(hexstr[i]); 52 u8 val; 53 54 if ((cur >= 'a' && cur <= 'f') || (cur >= '0' && cur <= '9')) { 55 val = cur - (cur > '9' ? 87 : 48); 56 57 if (i % 2 == 0) 58 acc = 16 * val; 59 else 60 (*result)[i / 2] = acc + val; 61 } else { 62 free(*result); 63 return 1; 64 } 65 } 66 67 return 0; 68 } 69 70 int extract_subprogram(u8 **progdata, u32 expected_magic, 71 struct key_program **result) 72 { 73 struct key_program *prog = *result; 74 u32 magic, code_crc, code_size; 75 76 magic = get_unaligned_be32(*progdata); 77 code_crc = get_unaligned_be32(*progdata + 4); 78 code_size = get_unaligned_be32(*progdata + 8); 79 80 *progdata += 12; 81 82 if (magic != expected_magic) 83 return -1; 84 85 *result = malloc(sizeof(struct key_program) + code_size); 86 87 if (!*result) 88 return -1; 89 90 prog->magic = magic; 91 prog->code_crc = code_crc; 92 prog->code_size = code_size; 93 memcpy(prog->code, *progdata, code_size); 94 95 *progdata += code_size; 96 97 if (hre_verify_program(prog)) { 98 free(prog); 99 return -1; 100 } 101 102 return 0; 103 } 104 105 struct key_program *parse_and_check_keyprog(u8 *progdata) 106 { 107 struct key_program *result = NULL, *hmac = NULL; 108 109 /* Part 1: Load key program */ 110 111 if (extract_subprogram(&progdata, MAGIC_KEY_PROGRAM, &result)) 112 return NULL; 113 114 /* Part 2: Load hmac program */ 115 116 if (extract_subprogram(&progdata, MAGIC_HMAC, &hmac)) 117 return NULL; 118 119 free(hmac); 120 121 return result; 122 } 123 124 int load_and_run_keyprog(void) 125 { 126 char *cmd = NULL; 127 u8 *binprog = NULL; 128 char *hexprog; 129 struct key_program *prog; 130 131 cmd = env_get("loadkeyprogram"); 132 133 if (!cmd || run_command(cmd, 0)) 134 return 1; 135 136 hexprog = env_get("keyprogram"); 137 138 if (decode_hexstr(hexprog, &binprog)) 139 return 1; 140 141 prog = parse_and_check_keyprog(binprog); 142 free(binprog); 143 144 if (!prog) 145 return 1; 146 147 if (hre_run_program(prog->code, prog->code_size)) { 148 free(prog); 149 return 1; 150 } 151 152 printf("\nSD code ran successfully\n"); 153 154 free(prog); 155 156 return 0; 157 } 158