├── INSTALL ├── README ├── common ├── cmd_sboot.c └── cmd_tpm_tlcl.c ├── drivers ├── i2c │ ├── omap24xx_i2c.c │ └── omap24xx_i2c.h └── tpm │ ├── Makefile │ ├── compatibility.h │ ├── tis_i2c.c │ ├── tpm.c │ ├── tpm.h │ ├── tpm_i2c_atmel.c │ ├── tpm_i2c_infineon.c │ └── tpm_lpc_generic.c ├── include ├── sboot.h ├── tlcl.h └── tss_constants.h ├── lib ├── sboot │ ├── Makefile │ ├── sboot.c │ └── spl_sboot.c └── tlcl │ ├── Makefile │ ├── oiaposap.c │ ├── oiaposap.h │ ├── oiaposap_structures.h │ ├── tlcl.c │ ├── tlcl_hmac.c │ ├── tlcl_internal.h │ ├── tlcl_keys.c │ ├── tlcl_seal.c │ ├── tlcl_seal.h │ ├── tlcl_structures.h │ └── tpm_error_messages.h └── patches ├── uboot-Makefile.patch ├── uboot-common-Makefile.patch ├── uboot-common-cmd_bootm.c.patch ├── uboot-common-env_common.c.patch ├── uboot-common-main.c.patch ├── uboot-common-spl-spl.c.patch ├── uboot-drivers-mmc-spl_mmc.c.patch ├── uboot-include-sha1.h.patch ├── uboot-lib-Makefile.patch ├── uboot-lib-sha1.c.patch └── uboot-spl-Makefile.patch /INSTALL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theopolis/sboot/45d94f05a35075f01818b91c421a3d1fdc754b2c/INSTALL -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | libSboot -- Standalone 2 | 3 | These libraries (libSboot, libTLCL) and TPM drivers provide a Secure Boot 4 | example for U-boot. A source tree with libSboot built into mainline U-Boot 5 | is available at https://github.com/theopolis/u-boot-sboot. 6 | 7 | Overview: 8 | ========= 9 | 10 | libSboot provides an example 'Secured Boot' for U-Boot and a U-Boot Second 11 | Phase Loader (SPL). libSboot attempts to define an example of how a platform 12 | can measure a pre-OS boot environment, thus providing a capability to 13 | ensure that a libSboot-enforced OS is only loaded in an owner-authorized 14 | fashion. A 'Secure Boot' concept is a common means to ensure platform security 15 | and integrity; understand that there are many implementations of a 'Secure 16 | Boot'. 17 | 18 | The pre-boot environment is defined as: 19 | - The U-Boot binary loaded by a SPL 20 | - EEPROM defining platform identification and configuration 21 | - Environment data read from an initial external source 22 | - Environment variables set via the U-Boot console 23 | - Commands interpreted via the U-Boot console 24 | - Flat Device Tree files 25 | - Initial Ram Disks and Ram Disks 26 | - An OS Kernel 27 | 28 | Currently libSboot does not require augmentation (signatures or keys) to 29 | data or configuration options for boot. It only requires patching U-Boot 30 | and SPL boot routines to measure and check platform state. This does not 31 | provide the user with much robustness. A change to the pre-boot environment 32 | will require interaction on the U-Boot console to 'reseal' the configuration. 33 | A more robust implementation would apply signature checking to data and options 34 | to provide flexible updates to the pre-boot environment. 35 | 36 | Understanding the implementation of libSboot: 37 | 38 | libSboot uses a TPM v1.2 to implement a secure boot using a static root 39 | of trust measurement (SRTM). The static adjective implies a 'read-only' 40 | attribute, meaning libSboot expects its initialization to occur from ROM code. 41 | During this initialization libSboot performs a TPM_Start, TPM_SelfTest and 42 | checks that the TPM is neither deactivated nor disabled. The TPM must have its 43 | NVRAM locked, meaning access control is enforced. Initialization then checks 44 | each PCR used to measure the pre-boot environment and verifies they are reset. 45 | Finally Physical Presence is asserted to satisfy NVRAM read/write permissions. 46 | 47 | The sealed data for a securely measured pre-boot environment is stored in TPM 48 | NVRAM with a Physical Presence requirement for read and write. Note: the sealed 49 | data is an encrypted blob, thus a Physical Presence requirement for reading is 50 | not required. Though the Physical Presence requirement for writing is very 51 | important! If arbitrary sealed data can be written, then an attacker can measure 52 | and store from a compromised OS state. Because of this, libSboot must de-assert 53 | Physical Presence and extend the PCRs with random data when libSboot finishes 54 | measuring or encounters an error. 55 | 56 | libSboot uses two sealed blobs stored in TPM NVRAM, one measured for the 57 | pre-execution of U-Boot, the other for the OS. This enables flexibility within 58 | U-Boot to seal modifications to the pre-boot environment for the U-Boot environment, 59 | U-Boot console usage, OS kernel, etc. Modifications to U-Boot are more difficult, 60 | U-Boot can issue a re-seal of a new U-Boot binary, but first the PCR which 61 | measured the running U-Boot must be reset. This requires an authenticated TPM_Reset 62 | command. 63 | 64 | libSboot will report to the console if an unseal fails, if libSboot is in 'enforce' 65 | (see below) mode then a failed unseal will halt execution. This implementation does 66 | not depend on the sealed and unsealed data (meaning we can seal well-known data), 67 | it only depends on the TPM response (success/failure) of an unseal. Since libSboot 68 | does not require authentication during initialization, subsequent initializations 69 | will normally fail. There are several ways to assure successful subsequent 70 | initializations: (1) build a method for authenticating a TPM owner within the SRTM; 71 | (2) require hardware Physical Presence; (3) issue a TPM Reset before the OS reboots. 72 | 73 | Setup: 74 | ====== 75 | 76 | 1. A working TPM. 77 | 2. Ownership of TPM; libSboot uses the Storage Root Key (SRK) for sealing 78 | measurements; the TPM must be protected against a reset. 79 | 3. TPM NVRAM locked. 80 | 4. Two NVRAM defined indexes with Physical Presence required for Read/Write. 81 | 5. Hardware write protection for the location of the SRTM (SPL). 82 | 83 | Configuration Options: 84 | ====================== 85 | 86 | - TPM Drivers 87 | 88 | CONFIG_TPM 89 | 90 | This will build libtpm, a TPM device will also need to be configured. 91 | 92 | CONFIG_TPM_I2C_ATMEL 93 | 94 | This selects a TPM device (Atmel's AT97SC3204T I2C TPM). A device on an 95 | I2C bus also needs to know it's bus ID and address. By default the first (0) 96 | I2C bus will be used. 97 | 98 | CONFIG_TPM_I2C_BUS 99 | 100 | For boards with multiple I2C buses, you may configure the bus number the 101 | TPM device is connected on. 102 | 103 | CONFIG_TPM_I2C_ADDR 104 | 105 | The address of the TPM on the I2C bus, usually specific to the device. 106 | 107 | CONFIG_CMD_TPM 108 | 109 | Enable the 'tpm' command within the U-Boot shell. The command accepts 110 | space-delimited characters to send to the TPM. 111 | 112 | - libTLCL (TPM Lite Library) 113 | This library provide the necessary TPM 1.2 Commands required for libSboot. 114 | 115 | CONFIG_TLCL_SEAL 116 | 117 | Adds TlclSeal, TlclUnseal and related methods to libTLCL. 118 | 119 | CONFIG_CMD_TPM_TLCL 120 | 121 | Enable the 'tpm_tlcl' command within the U-Boot shell. This command 122 | includes methods for testing the TPM. Warning! Some commands set permanent 123 | configuration options on the TPM. 124 | 125 | - libSboot 126 | 127 | CONFIG_SBOOT 128 | 129 | Adds libSboot to U-Boot. 130 | 131 | CONFIG_SPL_SBOOT_SUPPORT 132 | 133 | Adds libSboot to SPL. 134 | 135 | CONFIG_SBOOT_UBOOT_SEAL_INDEX 136 | 137 | Sets the NVRAM index to Seal/Unseal well-known blob data bound to the PCR 138 | values for a known-secure state before executing U-Boot. This option 139 | value is only used if CONFIG_SPL_SBOOT_SUPPORT is enabled. 140 | 141 | CONFIG_SBOOT_IMAGE_SEAL_INDEX 142 | 143 | Same as above, but for the state within U-Boot before executing an 144 | OS (kernel or otherwise). 145 | 146 | CONFIG_SBOOT_DISABLE_CONSOLE_EXTEND 147 | 148 | Prevent libSboot from measuring U-Boot console commands. 149 | (Not Recommended!) 150 | 151 | CONFIG_SBOOT_DISABLE_ENV_EXTEND 152 | 153 | Prevent libSboot from measuring U-Boot environments. 154 | This includes an external environment store, uEnv.txt, and environment 155 | variables set via the U-Boot shell (or other commands). 156 | (Not Recommended!) 157 | 158 | CONFIG_SBOOT_ENFORCE 159 | 160 | This will cause libSboot to halt execution if it fails to unseal for 161 | U-Boot or the OS. 162 | 163 | Notes: 164 | ====== 165 | 166 | This documentation is a work-in-progress. 167 | 168 | 169 | -------------------------------------------------------------------------------- /common/cmd_sboot.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cmd_sboot.c 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | static int test_seal(void) 13 | { 14 | uint8_t result; 15 | 16 | /* First we seal the currently running U-Boot */ 17 | printf("sboot: Sealing U-Boot\n"); 18 | result = sboot_seal_uboot(); 19 | if (result != SBOOT_SUCCESS) { 20 | printf("sboot: Failed to seal U-Boot\n"); 21 | return 0; 22 | } 23 | 24 | /* Then we tell bootm to seal the os, initrd, external environment, and dtb. 25 | * The user (and U-Boot) may continue to execute console commands and edit the 26 | * environment. All changes will be measured and sealed when bootm runs. 27 | * 28 | * To abort the seal, reset the device or unset the environment variable 'sbootseal'. 29 | */ 30 | puts("sboot: When bootm next runs, it will seal the boot state\n"); 31 | sboot_seal_toggle(); 32 | 33 | return 0; 34 | } 35 | 36 | /* u-boot command table (include/command.h) 37 | */ 38 | 39 | #define VOIDTEST(XFUNC) \ 40 | int do_test_##XFUNC(cmd_tbl_t *cmd_tbl, int flag, int argc, \ 41 | char * const argv[]) \ 42 | { \ 43 | return test_##XFUNC(); \ 44 | } \ 45 | 46 | /* above blank line is a part of the macro */ 47 | 48 | #define VOIDENT(XNAME) \ 49 | U_BOOT_CMD_MKENT(XNAME, 0, 1, do_test_##XNAME, "", "") 50 | 51 | VOIDTEST(seal) 52 | 53 | 54 | static cmd_tbl_t cmd_sboot_sub[] = { 55 | VOIDENT(seal), 56 | }; 57 | 58 | /* u-boot shell commands 59 | */ 60 | static int do_sboot(cmd_tbl_t * cmdtp, int flag, int argc, 61 | char * const argv[]) 62 | { 63 | cmd_tbl_t *c; 64 | printf("argc = %d, argv = ", argc); 65 | do { 66 | int i = 0; 67 | for (i = 0; i < argc; i++) 68 | printf(" %s", argv[i]); 69 | printf("\n------\n"); 70 | } while(0); 71 | argc--; 72 | argv++; 73 | c = find_cmd_tbl(argv[0], cmd_sboot_sub, 74 | ARRAY_SIZE(cmd_sboot_sub)); 75 | return c ? c->cmd(cmdtp, flag, argc, argv) : cmd_usage(cmdtp); 76 | } 77 | 78 | U_BOOT_CMD(sboot, 2, 1, do_sboot, "sboot commands", 79 | "\n\tseal\n" 80 | ); 81 | -------------------------------------------------------------------------------- /drivers/i2c/omap24xx_i2c.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Basic I2C functions 3 | * 4 | * Copyright (c) 2004 Texas Instruments 5 | * 6 | * This package is free software; you can redistribute it and/or 7 | * modify it under the terms of the license found in the file 8 | * named COPYING that should have accompanied this file. 9 | * 10 | * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 11 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 12 | * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 13 | * 14 | * Author: Jian Zhang jzhang@ti.com, Texas Instruments 15 | * 16 | * Copyright (c) 2003 Wolfgang Denk, wd@denx.de 17 | * Rewritten to fit into the current U-Boot framework 18 | * 19 | * Adapted for OMAP2420 I2C, r-woodruff2@ti.com 20 | * Multi-byte and Raw read, teddy@prosauce.org 21 | * 22 | */ 23 | 24 | #include 25 | 26 | #include 27 | #include 28 | 29 | #include "omap24xx_i2c.h" 30 | 31 | DECLARE_GLOBAL_DATA_PTR; 32 | 33 | #define I2C_TIMEOUT 1000 34 | 35 | static void wait_for_bb(void); 36 | static u16 wait_for_pin(void); 37 | static void flush_fifo(void); 38 | 39 | /* 40 | * For SPL boot some boards need i2c before SDRAM is initialised so force 41 | * variables to live in SRAM 42 | */ 43 | static struct i2c __attribute__((section (".data"))) *i2c_base = 44 | (struct i2c *)I2C_DEFAULT_BASE; 45 | static unsigned int __attribute__((section (".data"))) bus_initialized[I2C_BUS_MAX] = 46 | { [0 ... (I2C_BUS_MAX-1)] = 0 }; 47 | static unsigned int __attribute__((section (".data"))) current_bus = 0; 48 | 49 | void i2c_init(int speed, int slaveadd) 50 | { 51 | int psc, fsscll, fssclh; 52 | int hsscll = 0, hssclh = 0; 53 | u32 scll, sclh; 54 | int timeout = I2C_TIMEOUT; 55 | 56 | /* Only handle standard, fast and high speeds */ 57 | if ((speed != OMAP_I2C_STANDARD) && 58 | (speed != OMAP_I2C_FAST_MODE) && 59 | (speed != OMAP_I2C_HIGH_SPEED)) { 60 | printf("Error : I2C unsupported speed %d\n", speed); 61 | return; 62 | } 63 | 64 | psc = I2C_IP_CLK / I2C_INTERNAL_SAMPLING_CLK; 65 | psc -= 1; 66 | if (psc < I2C_PSC_MIN) { 67 | printf("Error : I2C unsupported prescalar %d\n", psc); 68 | return; 69 | } 70 | 71 | if (speed == OMAP_I2C_HIGH_SPEED) { 72 | /* High speed */ 73 | 74 | /* For first phase of HS mode */ 75 | fsscll = fssclh = I2C_INTERNAL_SAMPLING_CLK / 76 | (2 * OMAP_I2C_FAST_MODE); 77 | 78 | fsscll -= I2C_HIGHSPEED_PHASE_ONE_SCLL_TRIM; 79 | fssclh -= I2C_HIGHSPEED_PHASE_ONE_SCLH_TRIM; 80 | if (((fsscll < 0) || (fssclh < 0)) || 81 | ((fsscll > 255) || (fssclh > 255))) { 82 | puts("Error : I2C initializing first phase clock\n"); 83 | return; 84 | } 85 | 86 | /* For second phase of HS mode */ 87 | hsscll = hssclh = I2C_INTERNAL_SAMPLING_CLK / (2 * speed); 88 | 89 | hsscll -= I2C_HIGHSPEED_PHASE_TWO_SCLL_TRIM; 90 | hssclh -= I2C_HIGHSPEED_PHASE_TWO_SCLH_TRIM; 91 | if (((fsscll < 0) || (fssclh < 0)) || 92 | ((fsscll > 255) || (fssclh > 255))) { 93 | puts("Error : I2C initializing second phase clock\n"); 94 | return; 95 | } 96 | 97 | scll = (unsigned int)hsscll << 8 | (unsigned int)fsscll; 98 | sclh = (unsigned int)hssclh << 8 | (unsigned int)fssclh; 99 | 100 | } else { 101 | /* Standard and fast speed */ 102 | fsscll = fssclh = I2C_INTERNAL_SAMPLING_CLK / (2 * speed); 103 | 104 | fsscll -= I2C_FASTSPEED_SCLL_TRIM; 105 | fssclh -= I2C_FASTSPEED_SCLH_TRIM; 106 | if (((fsscll < 0) || (fssclh < 0)) || 107 | ((fsscll > 255) || (fssclh > 255))) { 108 | puts("Error : I2C initializing clock\n"); 109 | return; 110 | } 111 | 112 | scll = (unsigned int)fsscll; 113 | sclh = (unsigned int)fssclh; 114 | } 115 | 116 | if (readw(&i2c_base->con) & I2C_CON_EN) { 117 | writew(0, &i2c_base->con); 118 | udelay(50000); 119 | } 120 | 121 | writew(0x2, &i2c_base->sysc); /* for ES2 after soft reset */ 122 | udelay(1000); 123 | 124 | writew(I2C_CON_EN, &i2c_base->con); 125 | while (!(readw(&i2c_base->syss) & I2C_SYSS_RDONE) && timeout--) { 126 | if (timeout <= 0) { 127 | puts("ERROR: Timeout in soft-reset\n"); 128 | return; 129 | } 130 | udelay(1000); 131 | } 132 | 133 | writew(0, &i2c_base->con); 134 | writew(psc, &i2c_base->psc); 135 | writew(scll, &i2c_base->scll); 136 | writew(sclh, &i2c_base->sclh); 137 | 138 | /* own address */ 139 | writew(slaveadd, &i2c_base->oa); 140 | writew(I2C_CON_EN, &i2c_base->con); 141 | 142 | /* have to enable intrrupts or OMAP i2c module doesn't work */ 143 | writew(I2C_IE_XRDY_IE | I2C_IE_RRDY_IE | I2C_IE_ARDY_IE | 144 | I2C_IE_NACK_IE | I2C_IE_AL_IE, &i2c_base->ie); 145 | udelay(1000); 146 | flush_fifo(); 147 | writew(0xFFFF, &i2c_base->stat); 148 | writew(0, &i2c_base->cnt); 149 | 150 | if (gd->flags & GD_FLG_RELOC) 151 | bus_initialized[current_bus] = 1; 152 | } 153 | 154 | static int i2c_read_byte(u8 devaddr, u16 regoffset, u8 alen, u16 len, u8 *value) 155 | { 156 | int i2c_error = 0; 157 | u16 status; 158 | int i = 2 - alen; 159 | u8 tmpbuf[64] = {(regoffset) >> 8, regoffset & 0xff}; 160 | u16 w; 161 | 162 | /* wait until bus not busy */ 163 | wait_for_bb(); 164 | 165 | if (alen > 0) { 166 | 167 | /* one byte only */ 168 | writew(alen, &i2c_base->cnt); 169 | /* set slave address */ 170 | writew(devaddr, &i2c_base->sa); 171 | /* no stop bit needed here */ 172 | writew(I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX, &i2c_base->con); 173 | 174 | memset(tmpbuf + 2, 0, 62); /*oddness*/ 175 | /* send register offset */ 176 | while (1) { 177 | status = wait_for_pin(); 178 | 179 | if (status == 0 || (status & I2C_STAT_NACK)) { 180 | i2c_error = 1; 181 | goto read_exit; 182 | } 183 | 184 | if (status & I2C_STAT_XRDY) { 185 | w = tmpbuf[i++]; 186 | #if !(defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) || \ 187 | defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX)) 188 | w |= tmpbuf[i++] << 8; 189 | #endif 190 | writew(w, &i2c_base->data); 191 | writew(I2C_STAT_XRDY, &i2c_base->stat); 192 | } 193 | 194 | if (status & I2C_STAT_ARDY) { 195 | writew(I2C_STAT_ARDY, &i2c_base->stat); 196 | break; 197 | } 198 | } 199 | } 200 | 201 | /* set slave address */ 202 | writew(devaddr, &i2c_base->sa); 203 | /* read len byte(s) from slave */ 204 | writew(len, &i2c_base->cnt); 205 | /* need stop bit here */ 206 | flush_fifo(); 207 | writew(I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP, 208 | &i2c_base->con); 209 | 210 | /* receive data */ 211 | while (1) { 212 | status = wait_for_pin(); 213 | if (status & I2C_STAT_AL) { 214 | i2c_error = 1; 215 | goto read_exit; 216 | } 217 | if (status == 0 || (status & I2C_STAT_NACK)) { 218 | i2c_error = 1; 219 | goto read_exit; 220 | } 221 | if (status & I2C_STAT_RRDY) { 222 | #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) || \ 223 | defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX) 224 | *value = readb(&i2c_base->data); 225 | ++value; /* instead of reading buff size reg, just inc by 1 */ 226 | #else 227 | *value = readw(&i2c_base->data); 228 | #endif 229 | writew(I2C_STAT_RRDY, &i2c_base->stat); 230 | } 231 | if (status & I2C_STAT_ARDY) { 232 | writew(I2C_STAT_ARDY, &i2c_base->stat); 233 | break; 234 | } 235 | } 236 | 237 | read_exit: 238 | flush_fifo(); 239 | writew(0xFFFF, &i2c_base->stat); 240 | writew(0, &i2c_base->cnt); 241 | return i2c_error; 242 | } 243 | 244 | 245 | 246 | static void flush_fifo(void) 247 | { u16 stat; 248 | 249 | /* note: if you try and read data when its not there or ready 250 | * you get a bus error 251 | */ 252 | while (1) { 253 | stat = readw(&i2c_base->stat); 254 | if (stat == I2C_STAT_RRDY) { 255 | #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) || \ 256 | defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX) 257 | readb(&i2c_base->data); 258 | #else 259 | readw(&i2c_base->data); 260 | #endif 261 | writew(I2C_STAT_RRDY, &i2c_base->stat); 262 | udelay(1000); 263 | } else 264 | break; 265 | } 266 | } 267 | 268 | int i2c_probe(uchar chip) 269 | { 270 | u16 status; 271 | int res = 1; /* default = fail */ 272 | 273 | if (chip == readw(&i2c_base->oa)) 274 | return res; 275 | 276 | /* wait until bus not busy */ 277 | wait_for_bb(); 278 | 279 | /* try to read one byte */ 280 | writew(1, &i2c_base->cnt); 281 | /* set slave address */ 282 | writew(chip, &i2c_base->sa); 283 | /* stop bit needed here */ 284 | writew (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP, &i2c_base->con); 285 | 286 | while (1) { 287 | status = wait_for_pin(); 288 | if (status == 0 || status & I2C_STAT_AL) { 289 | res = 1; 290 | goto probe_exit; 291 | } 292 | if (status & I2C_STAT_NACK) { 293 | res = 1; 294 | writew(0xff, &i2c_base->stat); 295 | writew (readw (&i2c_base->con) | I2C_CON_STP, &i2c_base->con); 296 | wait_for_bb (); 297 | break; 298 | } 299 | if (status & I2C_STAT_ARDY) { 300 | writew(I2C_STAT_ARDY, &i2c_base->stat); 301 | break; 302 | } 303 | if (status & I2C_STAT_RRDY) { 304 | res = 0; 305 | #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) || \ 306 | defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX) 307 | readb(&i2c_base->data); 308 | #else 309 | readw(&i2c_base->data); 310 | #endif 311 | writew(I2C_STAT_RRDY, &i2c_base->stat); 312 | } 313 | } 314 | 315 | probe_exit: 316 | flush_fifo(); 317 | /* don't allow any more data in... we don't want it. */ 318 | writew(0, &i2c_base->cnt); 319 | writew(0xFFFF, &i2c_base->stat); 320 | return res; 321 | } 322 | 323 | int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) 324 | { 325 | if (alen > 2) { 326 | printf("I2C read: addr len %d not supported\n", alen); 327 | return 1; 328 | } 329 | 330 | if (addr + len > (1 << 16)) { 331 | puts("I2C read: address out of range\n"); 332 | return 1; 333 | } 334 | 335 | if (i2c_read_byte(chip, addr, alen, len, buffer)) { 336 | i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); 337 | return 1; 338 | } 339 | 340 | return 0; 341 | } 342 | 343 | int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len) 344 | { 345 | int i; 346 | u16 status; 347 | int i2c_error = 0; 348 | u16 w; 349 | u8 tmpbuf[2] = {addr >> 8, addr & 0xff}; 350 | 351 | if (alen > 2) { 352 | printf("I2C write: addr len %d not supported\n", alen); 353 | return 1; 354 | } 355 | 356 | if (addr + len > (1 << 16)) { 357 | printf("I2C write: address 0x%x + 0x%x out of range\n", 358 | addr, len); 359 | return 1; 360 | } 361 | 362 | /* wait until bus not busy */ 363 | wait_for_bb(); 364 | 365 | /* start address phase - will write regoffset + len bytes data */ 366 | /* TODO consider case when !CONFIG_OMAP243X/34XX/44XX */ 367 | writew(alen + len, &i2c_base->cnt); 368 | /* set slave address */ 369 | writew(chip, &i2c_base->sa); 370 | /* stop bit needed here */ 371 | writew(I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX | 372 | I2C_CON_STP, &i2c_base->con); 373 | 374 | /* Send address and data */ 375 | for (i = -alen; i < len; i++) { 376 | status = wait_for_pin(); 377 | if (status == 0 || (status & I2C_STAT_NACK)) { 378 | i2c_error = 1; 379 | goto write_exit; 380 | } 381 | 382 | if (status & I2C_STAT_XRDY) { 383 | w = (i < 0) ? tmpbuf[2+i] : buffer[i]; 384 | #if !(defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) || \ 385 | defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX)) 386 | w |= ((++i < 0) ? tmpbuf[2+i] : buffer[i]) << 8; 387 | #endif 388 | writew(w, &i2c_base->data); 389 | writew(I2C_STAT_XRDY, &i2c_base->stat); 390 | } else { 391 | i2c_error = 1; 392 | goto write_exit; 393 | } 394 | } 395 | 396 | status = wait_for_pin(); 397 | writew(I2C_CON_EN, &i2c_base->con); 398 | 399 | write_exit: 400 | flush_fifo(); 401 | writew(0, &i2c_base->cnt); 402 | writew(0xFFFF, &i2c_base->stat); 403 | return i2c_error; 404 | } 405 | 406 | static void wait_for_bb(void) 407 | { 408 | int timeout = I2C_TIMEOUT; 409 | u16 stat; 410 | 411 | writew(0xFFFF, &i2c_base->stat); /* clear current interrupts...*/ 412 | while ((stat = readw(&i2c_base->stat) & I2C_STAT_BB) && timeout--) { 413 | writew(stat, &i2c_base->stat); 414 | udelay(1000); 415 | } 416 | 417 | if (timeout <= 0) { 418 | printf("timed out in wait_for_bb: I2C_STAT=%x\n", 419 | readw(&i2c_base->stat)); 420 | } 421 | writew(0xFFFF, &i2c_base->stat); /* clear delayed stuff*/ 422 | } 423 | 424 | static u16 wait_for_pin(void) 425 | { 426 | u16 status; 427 | int timeout = I2C_TIMEOUT; 428 | 429 | do { 430 | udelay(1000); 431 | status = readw(&i2c_base->stat); 432 | } while (!(status & 433 | (I2C_STAT_ROVR | I2C_STAT_XUDF | I2C_STAT_XRDY | 434 | I2C_STAT_RRDY | I2C_STAT_ARDY | I2C_STAT_NACK | 435 | I2C_STAT_AL)) && timeout--); 436 | 437 | if (timeout <= 0) { 438 | printf("timed out in wait_for_pin: I2C_STAT=%x\n", 439 | readw(&i2c_base->stat)); 440 | writew(0xFFFF, &i2c_base->stat); 441 | status = 0; 442 | } 443 | 444 | return status; 445 | } 446 | 447 | int i2c_set_bus_num(unsigned int bus) 448 | { 449 | if ((bus < 0) || (bus >= I2C_BUS_MAX)) { 450 | printf("Bad bus: %d\n", bus); 451 | return -1; 452 | } 453 | 454 | #if I2C_BUS_MAX == 4 455 | if (bus == 3) 456 | i2c_base = (struct i2c *)I2C_BASE4; 457 | else 458 | if (bus == 2) 459 | i2c_base = (struct i2c *)I2C_BASE3; 460 | else 461 | #endif 462 | #if I2C_BUS_MAX == 3 463 | if (bus == 2) 464 | i2c_base = (struct i2c *)I2C_BASE3; 465 | else 466 | #endif 467 | if (bus == 1) 468 | i2c_base = (struct i2c *)I2C_BASE2; 469 | else 470 | i2c_base = (struct i2c *)I2C_BASE1; 471 | 472 | current_bus = bus; 473 | 474 | if (!bus_initialized[current_bus]) 475 | i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); 476 | 477 | return 0; 478 | } 479 | 480 | int i2c_get_bus_num(void) 481 | { 482 | return (int) current_bus; 483 | } 484 | -------------------------------------------------------------------------------- /drivers/i2c/omap24xx_i2c.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) Copyright 2004-2010 3 | * Texas Instruments, 4 | * 5 | * See file CREDITS for list of people who contributed to this 6 | * project. 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License as 10 | * published by the Free Software Foundation; either version 2 of 11 | * the License, or (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 21 | * MA 02111-1307 USA 22 | */ 23 | #ifndef _OMAP2PLUS_I2C_H_ 24 | #define _OMAP2PLUS_I2C_H_ 25 | 26 | /* I2C masks */ 27 | 28 | /* I2C Interrupt Enable Register (I2C_IE): */ 29 | #define I2C_IE_GC_IE (1 << 5) 30 | #define I2C_IE_XRDY_IE (1 << 4) /* Transmit data ready interrupt enable */ 31 | #define I2C_IE_RRDY_IE (1 << 3) /* Receive data ready interrupt enable */ 32 | #define I2C_IE_ARDY_IE (1 << 2) /* Register access ready interrupt enable */ 33 | #define I2C_IE_NACK_IE (1 << 1) /* No acknowledgment interrupt enable */ 34 | #define I2C_IE_AL_IE (1 << 0) /* Arbitration lost interrupt enable */ 35 | 36 | /* I2C Status Register (I2C_STAT): */ 37 | 38 | #define I2C_STAT_SBD (1 << 15) /* Single byte data */ 39 | #define I2C_STAT_BB (1 << 12) /* Bus busy */ 40 | #define I2C_STAT_ROVR (1 << 11) /* Receive overrun */ 41 | #define I2C_STAT_XUDF (1 << 10) /* Transmit underflow */ 42 | #define I2C_STAT_AAS (1 << 9) /* Address as slave */ 43 | #define I2C_STAT_GC (1 << 5) 44 | #define I2C_STAT_XRDY (1 << 4) /* Transmit data ready */ 45 | #define I2C_STAT_RRDY (1 << 3) /* Receive data ready */ 46 | #define I2C_STAT_ARDY (1 << 2) /* Register access ready */ 47 | #define I2C_STAT_NACK (1 << 1) /* No acknowledgment interrupt enable */ 48 | #define I2C_STAT_AL (1 << 0) /* Arbitration lost interrupt enable */ 49 | 50 | /* I2C Interrupt Code Register (I2C_INTCODE): */ 51 | 52 | #define I2C_INTCODE_MASK 7 53 | #define I2C_INTCODE_NONE 0 54 | #define I2C_INTCODE_AL 1 /* Arbitration lost */ 55 | #define I2C_INTCODE_NAK 2 /* No acknowledgement/general call */ 56 | #define I2C_INTCODE_ARDY 3 /* Register access ready */ 57 | #define I2C_INTCODE_RRDY 4 /* Rcv data ready */ 58 | #define I2C_INTCODE_XRDY 5 /* Xmit data ready */ 59 | 60 | /* I2C Buffer Configuration Register (I2C_BUF): */ 61 | 62 | #define I2C_BUF_RDMA_EN (1 << 15) /* Receive DMA channel enable */ 63 | #define I2C_BUF_RXFIF_CLR (1 << 14) /* RX FIFO Clear */ 64 | #define I2C_BUF_XDMA_EN (1 << 7) /* Transmit DMA channel enable */ 65 | #define I2C_BUF_TXFIF_CLR (1 << 6) /* TX FIFO Clear */ 66 | 67 | /* I2C Configuration Register (I2C_CON): */ 68 | 69 | #define I2C_CON_EN (1 << 15) /* I2C module enable */ 70 | #define I2C_CON_BE (1 << 14) /* Big endian mode */ 71 | #define I2C_CON_STB (1 << 11) /* Start byte mode (master mode only) */ 72 | #define I2C_CON_MST (1 << 10) /* Master/slave mode */ 73 | #define I2C_CON_TRX (1 << 9) /* Transmitter/receiver mode */ 74 | /* (master mode only) */ 75 | #define I2C_CON_XA (1 << 8) /* Expand address */ 76 | #define I2C_CON_STP (1 << 1) /* Stop condition (master mode only) */ 77 | #define I2C_CON_STT (1 << 0) /* Start condition (master mode only) */ 78 | 79 | /* I2C System Test Register (I2C_SYSTEST): */ 80 | 81 | #define I2C_SYSTEST_ST_EN (1 << 15) /* System test enable */ 82 | #define I2C_SYSTEST_FREE (1 << 14) /* Free running mode, on brkpoint) */ 83 | #define I2C_SYSTEST_TMODE_MASK (3 << 12) /* Test mode select */ 84 | #define I2C_SYSTEST_TMODE_SHIFT (12) /* Test mode select */ 85 | #define I2C_SYSTEST_SCL_I (1 << 3) /* SCL line sense input value */ 86 | #define I2C_SYSTEST_SCL_O (1 << 2) /* SCL line drive output value */ 87 | #define I2C_SYSTEST_SDA_I (1 << 1) /* SDA line sense input value */ 88 | #define I2C_SYSTEST_SDA_O (1 << 0) /* SDA line drive output value */ 89 | 90 | /* I2C Buffer Status Register (I2C_BUFSTAT): */ 91 | 92 | #define I2C_BUFSTAT_FIFODEPTH_MASK (3 << 14) /* FIFO buffers depth */ 93 | #define I2C_BUFSTAT_FIFODEPTH_SHIFT (14) /* FIFO buffers depth */ 94 | #define I2C_BUFSTAT_RXSTAT_MASK (0x3f << 8) /* RX Buffer Status */ 95 | #define I2C_BUFSTAT_RXSTAT_SHIFT (8) /* RX Buffer Status */ 96 | #define I2C_BUFSTAT_TXSTAT_MASK (0x3f << 0) /* TX Buffer Status */ 97 | 98 | /* I2C System Status Register (I2C_SYSS): */ 99 | 100 | #define I2C_SYSS_RDONE (1 << 0) /* Internel reset monitoring */ 101 | 102 | #define I2C_SCLL_SCLL 0 103 | #define I2C_SCLL_SCLL_M 0xFF 104 | #define I2C_SCLL_HSSCLL 8 105 | #define I2C_SCLH_HSSCLL_M 0xFF 106 | #define I2C_SCLH_SCLH 0 107 | #define I2C_SCLH_SCLH_M 0xFF 108 | #define I2C_SCLH_HSSCLH 8 109 | #define I2C_SCLH_HSSCLH_M 0xFF 110 | 111 | #define OMAP_I2C_STANDARD 100000 112 | #define OMAP_I2C_FAST_MODE 400000 113 | #define OMAP_I2C_HIGH_SPEED 3400000 114 | 115 | #define SYSTEM_CLOCK_12 12000000 116 | #define SYSTEM_CLOCK_13 13000000 117 | #define SYSTEM_CLOCK_192 19200000 118 | #define SYSTEM_CLOCK_96 96000000 119 | 120 | /* Use the reference value of 96MHz if not explicitly set by the board */ 121 | #ifndef I2C_IP_CLK 122 | #define I2C_IP_CLK SYSTEM_CLOCK_96 123 | #endif 124 | 125 | /* 126 | * The reference minimum clock for high speed is 19.2MHz. 127 | * The linux 2.6.30 kernel uses this value. 128 | * The reference minimum clock for fast mode is 9.6MHz 129 | * The reference minimum clock for standard mode is 4MHz 130 | * In TRM, the value of 12MHz is used. 131 | */ 132 | #ifndef I2C_INTERNAL_SAMPLING_CLK 133 | #define I2C_INTERNAL_SAMPLING_CLK 19200000 134 | #endif 135 | 136 | /* 137 | * The equation for the low and high time is 138 | * tlow = scll + scll_trim = (sampling clock * tlow_duty) / speed 139 | * thigh = sclh + sclh_trim = (sampling clock * (1 - tlow_duty)) / speed 140 | * 141 | * If the duty cycle is 50% 142 | * 143 | * tlow = scll + scll_trim = sampling clock / (2 * speed) 144 | * thigh = sclh + sclh_trim = sampling clock / (2 * speed) 145 | * 146 | * In TRM 147 | * scll_trim = 7 148 | * sclh_trim = 5 149 | * 150 | * The linux 2.6.30 kernel uses 151 | * scll_trim = 6 152 | * sclh_trim = 6 153 | * 154 | * These are the trim values for standard and fast speed 155 | */ 156 | #ifndef I2C_FASTSPEED_SCLL_TRIM 157 | #define I2C_FASTSPEED_SCLL_TRIM 6 158 | #endif 159 | #ifndef I2C_FASTSPEED_SCLH_TRIM 160 | #define I2C_FASTSPEED_SCLH_TRIM 6 161 | #endif 162 | 163 | /* These are the trim values for high speed */ 164 | #ifndef I2C_HIGHSPEED_PHASE_ONE_SCLL_TRIM 165 | #define I2C_HIGHSPEED_PHASE_ONE_SCLL_TRIM I2C_FASTSPEED_SCLL_TRIM 166 | #endif 167 | #ifndef I2C_HIGHSPEED_PHASE_ONE_SCLH_TRIM 168 | #define I2C_HIGHSPEED_PHASE_ONE_SCLH_TRIM I2C_FASTSPEED_SCLH_TRIM 169 | #endif 170 | #ifndef I2C_HIGHSPEED_PHASE_TWO_SCLL_TRIM 171 | #define I2C_HIGHSPEED_PHASE_TWO_SCLL_TRIM I2C_FASTSPEED_SCLL_TRIM 172 | #endif 173 | #ifndef I2C_HIGHSPEED_PHASE_TWO_SCLH_TRIM 174 | #define I2C_HIGHSPEED_PHASE_TWO_SCLH_TRIM I2C_FASTSPEED_SCLH_TRIM 175 | #endif 176 | 177 | #define I2C_PSC_MAX 0x0f 178 | #define I2C_PSC_MIN 0x00 179 | 180 | #endif /* _OMAP24XX_I2C_H_ */ 181 | -------------------------------------------------------------------------------- /drivers/tpm/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2011 The Chromium OS Authors. All rights reserved. 2 | # 3 | # See file CREDITS for list of people who contributed to this 4 | # project. 5 | # 6 | # This program is free software; you can redistribute it and/or 7 | # modify it under the terms of the GNU General Public License as 8 | # published by the Free Software Foundation; either version 2 of 9 | # the License, or (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program; if not, write to the Free Software 18 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, 19 | # MA 02111-1307 USA 20 | # 21 | 22 | include $(TOPDIR)/config.mk 23 | 24 | LIB := $(obj)libtpm.o 25 | 26 | COBJS-$(CONFIG_TPM_I2C_ATMEL) = tis_i2c.o tpm.o tpm_i2c_atmel.o 27 | COBJS-$(CONFIG_GENERIC_LPC_TPM) = tpm_lpc_generic.o 28 | COBJS-$(CONFIG_INFINEON_TPM_I2C) = tis_i2c.o tpm.o tpm_i2c_infineon.o 29 | 30 | COBJS := $(COBJS-y) 31 | SRCS := $(COBJS:.o=.c) 32 | OBJS := $(addprefix $(obj),$(COBJS)) 33 | 34 | all: $(LIB) 35 | 36 | $(LIB): $(obj).depend $(OBJS) 37 | $(call cmd_link_o_target, $(OBJS)) 38 | 39 | ######################################################################### 40 | 41 | include $(SRCTREE)/rules.mk 42 | 43 | sinclude $(obj).depend 44 | 45 | ######################################################################### 46 | -------------------------------------------------------------------------------- /drivers/tpm/compatibility.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Infineon Technologies 3 | * 4 | * Authors: 5 | * Peter Huewe 6 | * 7 | * Version: 2.1.1 8 | * 9 | * See file CREDITS for list of people who contributed to this 10 | * project. 11 | * 12 | * This program is free software; you can redistribute it and/or 13 | * modify it under the terms of the GNU General Public License as 14 | * published by the Free Software Foundation; either version 2 of 15 | * the License, or (at your option) any later version. 16 | * 17 | * This program is distributed in the hope that it will be useful, 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | * GNU General Public License for more details. 21 | * 22 | * You should have received a copy of the GNU General Public License 23 | * along with this program; if not, write to the Free Software 24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 25 | * MA 02111-1307 USA 26 | */ 27 | 28 | #ifndef _COMPATIBILITY_H_ 29 | #define _COMPATIBILITY_H_ 30 | 31 | /* all includes from U-Boot */ 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | /* extended error numbers from linux (see errno.h) */ 39 | #define ECANCELED 125 /* Operation Canceled */ 40 | 41 | #define msleep(t) udelay((t)*1000) 42 | 43 | /* Timer frequency. Corresponds to msec timer resolution*/ 44 | #define HZ 1000 45 | 46 | 47 | #define dev_dbg(dev, format, arg...) debug(format, ##arg) 48 | #define dev_err(dev, format, arg...) printf(format, ##arg) 49 | #define dev_info(dev, format, arg...) debug(format, ##arg) 50 | #define dbg_printf debug 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /drivers/tpm/tis_i2c.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include "tpm.h" 11 | 12 | DECLARE_GLOBAL_DATA_PTR; 13 | 14 | /* Define in board config */ 15 | #ifndef CONFIG_TPM_I2C_BUS 16 | #define CONFIG_TPM_I2C_BUS 0 17 | #define CONFIG_TPM_I2C_ADDR 0 18 | #endif 19 | 20 | /* TPM configuration */ 21 | struct tpm { 22 | int i2c_bus; 23 | int slave_addr; 24 | char inited; 25 | int old_bus; 26 | } tpm; 27 | 28 | 29 | static int tpm_select(void) 30 | { 31 | int ret; 32 | 33 | tpm.old_bus = i2c_get_bus_num(); 34 | if (tpm.old_bus != tpm.i2c_bus) { 35 | ret = i2c_set_bus_num(tpm.i2c_bus); 36 | if (ret) { 37 | debug("%s: Fail to set i2c bus %d\n", __func__, 38 | tpm.i2c_bus); 39 | return -1; 40 | } 41 | } 42 | return 0; 43 | } 44 | 45 | static int tpm_deselect(void) 46 | { 47 | int ret; 48 | 49 | if (tpm.old_bus != i2c_get_bus_num()) { 50 | ret = i2c_set_bus_num(tpm.old_bus); 51 | if (ret) { 52 | debug("%s: Fail to restore i2c bus %d\n", 53 | __func__, tpm.old_bus); 54 | return -1; 55 | } 56 | } 57 | tpm.old_bus = -1; 58 | return 0; 59 | } 60 | 61 | /** 62 | * Decode TPM configuration. 63 | * 64 | * @param dev Returns a configuration of TPM device 65 | * @return 0 if ok, -1 on error 66 | */ 67 | static int tpm_decode_config(struct tpm *dev) 68 | { 69 | #ifdef CONFIG_OF_CONTROL 70 | const void *blob = gd->fdt_blob; 71 | int node, parent; 72 | int i2c_bus; 73 | 74 | node = fdtdec_next_compatible(blob, 0, COMPAT_INFINEON_SLB9635_TPM); 75 | if (node < 0) { 76 | debug("%s: Node not found\n", __func__); 77 | return -1; 78 | } 79 | parent = fdt_parent_offset(blob, node); 80 | if (parent < 0) { 81 | debug("%s: Cannot find node parent\n", __func__); 82 | return -1; 83 | } 84 | i2c_bus = i2c_get_bus_num_fdt(blob, parent); 85 | if (i2c_bus < 0) 86 | return -1; 87 | dev->i2c_bus = i2c_bus; 88 | dev->slave_addr = fdtdec_get_addr(blob, node, "reg"); 89 | #else 90 | dev->i2c_bus = CONFIG_TPM_I2C_BUS; 91 | dev->slave_addr = CONFIG_TPM_I2C_ADDR; 92 | #endif 93 | return 0; 94 | } 95 | 96 | /* Methods used by cmd_tpm */ 97 | int tis_init(void) 98 | { 99 | if (tpm.inited) 100 | return 0; 101 | 102 | if (tpm_decode_config(&tpm)) 103 | return -1; 104 | 105 | if (tpm_select()) 106 | return -1; 107 | 108 | /* 109 | * Probe TPM twice; the first probing might fail because TPM is asleep, 110 | * and the probing can wake up TPM. 111 | */ 112 | if (i2c_probe(tpm.slave_addr) && i2c_probe(tpm.slave_addr)) { 113 | debug("%s: fail to probe i2c addr 0x%x\n", __func__, 114 | tpm.slave_addr); 115 | return -1; 116 | } 117 | 118 | tpm_deselect(); 119 | 120 | tpm.inited = 1; 121 | 122 | return 0; 123 | } 124 | 125 | int tis_open(void) 126 | { 127 | int rc; 128 | 129 | if (!tpm.inited) 130 | return -1; 131 | 132 | if (tpm_select()) 133 | return -1; 134 | 135 | rc = tpm_open(tpm.slave_addr); 136 | 137 | tpm_deselect(); 138 | 139 | return rc; 140 | } 141 | 142 | int tis_close(void) 143 | { 144 | if (!tpm.inited) 145 | return -1; 146 | 147 | if (tpm_select()) 148 | return -1; 149 | 150 | tpm_close(); 151 | 152 | tpm_deselect(); 153 | 154 | return 0; 155 | } 156 | 157 | int tis_sendrecv(const uint8_t *sendbuf, size_t sbuf_size, 158 | uint8_t *recvbuf, size_t *rbuf_len) 159 | { 160 | int len; 161 | uint8_t buf[TPM_BUFSIZE]; 162 | 163 | if (!tpm.inited) 164 | return -1; 165 | 166 | if (sizeof(buf) < sbuf_size) 167 | return -1; 168 | 169 | memcpy(buf, sendbuf, sbuf_size); 170 | 171 | if (tpm_select()) 172 | return -1; 173 | 174 | len = tpm_transmit(buf, sbuf_size); 175 | 176 | tpm_deselect(); 177 | 178 | if (len < 10) { 179 | *rbuf_len = 0; 180 | return -1; 181 | } 182 | 183 | memcpy(recvbuf, buf, len); 184 | *rbuf_len = len; 185 | 186 | return 0; 187 | } 188 | -------------------------------------------------------------------------------- /drivers/tpm/tpm.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Infineon Technologies 3 | * 4 | * Authors: 5 | * Peter Huewe 6 | * 7 | * Description: 8 | * Device driver for TCG/TCPA TPM (trusted platform module). 9 | * Specifications at www.trustedcomputinggroup.org 10 | * 11 | * It is based on the Linux kernel driver tpm.c from Leendert van 12 | * Dorn, Dave Safford, Reiner Sailer, and Kyleen Hall. 13 | * 14 | * Version: 2.1.1 15 | * 16 | * See file CREDITS for list of people who contributed to this 17 | * project. 18 | * 19 | * This program is free software; you can redistribute it and/or 20 | * modify it under the terms of the GNU General Public License as 21 | * published by the Free Software Foundation, version 2 of the 22 | * License. 23 | * 24 | * This program is distributed in the hope that it will be useful, 25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | * GNU General Public License for more details. 28 | * 29 | * You should have received a copy of the GNU General Public License 30 | * along with this program; if not, write to the Free Software 31 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 32 | * MA 02111-1307 USA 33 | */ 34 | 35 | #include 36 | #include "tpm.h" 37 | 38 | /* global structure for tpm chip data */ 39 | struct tpm_chip g_chip; 40 | 41 | enum tpm_duration { 42 | TPM_SHORT = 0, 43 | TPM_MEDIUM = 1, 44 | TPM_LONG = 2, 45 | TPM_UNDEFINED, 46 | }; 47 | 48 | #define TPM_MAX_ORDINAL 243 49 | #define TPM_MAX_PROTECTED_ORDINAL 12 50 | #define TPM_PROTECTED_ORDINAL_MASK 0xFF 51 | 52 | /* 53 | * Array with one entry per ordinal defining the maximum amount 54 | * of time the chip could take to return the result. The ordinal 55 | * designation of short, medium or long is defined in a table in 56 | * TCG Specification TPM Main Part 2 TPM Structures Section 17. The 57 | * values of the SHORT, MEDIUM, and LONG durations are retrieved 58 | * from the chip during initialization with a call to tpm_get_timeouts. 59 | */ 60 | static const u8 tpm_protected_ordinal_duration[TPM_MAX_PROTECTED_ORDINAL] = { 61 | TPM_UNDEFINED, /* 0 */ 62 | TPM_UNDEFINED, 63 | TPM_UNDEFINED, 64 | TPM_UNDEFINED, 65 | TPM_UNDEFINED, 66 | TPM_UNDEFINED, /* 5 */ 67 | TPM_UNDEFINED, 68 | TPM_UNDEFINED, 69 | TPM_UNDEFINED, 70 | TPM_UNDEFINED, 71 | TPM_SHORT, /* 10 */ 72 | TPM_SHORT, 73 | }; 74 | 75 | static const u8 tpm_ordinal_duration[TPM_MAX_ORDINAL] = { 76 | TPM_UNDEFINED, /* 0 */ 77 | TPM_UNDEFINED, 78 | TPM_UNDEFINED, 79 | TPM_UNDEFINED, 80 | TPM_UNDEFINED, 81 | TPM_UNDEFINED, /* 5 */ 82 | TPM_UNDEFINED, 83 | TPM_UNDEFINED, 84 | TPM_UNDEFINED, 85 | TPM_UNDEFINED, 86 | TPM_SHORT, /* 10 */ 87 | TPM_SHORT, 88 | TPM_MEDIUM, 89 | TPM_LONG, 90 | TPM_LONG, 91 | TPM_MEDIUM, /* 15 */ 92 | TPM_SHORT, 93 | TPM_SHORT, 94 | TPM_MEDIUM, 95 | TPM_LONG, 96 | TPM_SHORT, /* 20 */ 97 | TPM_SHORT, 98 | TPM_MEDIUM, 99 | TPM_MEDIUM, 100 | TPM_MEDIUM, 101 | TPM_SHORT, /* 25 */ 102 | TPM_SHORT, 103 | TPM_MEDIUM, 104 | TPM_SHORT, 105 | TPM_SHORT, 106 | TPM_MEDIUM, /* 30 */ 107 | TPM_LONG, 108 | TPM_MEDIUM, 109 | TPM_SHORT, 110 | TPM_SHORT, 111 | TPM_SHORT, /* 35 */ 112 | TPM_MEDIUM, 113 | TPM_MEDIUM, 114 | TPM_UNDEFINED, 115 | TPM_UNDEFINED, 116 | TPM_MEDIUM, /* 40 */ 117 | TPM_LONG, 118 | TPM_MEDIUM, 119 | TPM_SHORT, 120 | TPM_SHORT, 121 | TPM_SHORT, /* 45 */ 122 | TPM_SHORT, 123 | TPM_SHORT, 124 | TPM_SHORT, 125 | TPM_LONG, 126 | TPM_MEDIUM, /* 50 */ 127 | TPM_MEDIUM, 128 | TPM_UNDEFINED, 129 | TPM_UNDEFINED, 130 | TPM_UNDEFINED, 131 | TPM_UNDEFINED, /* 55 */ 132 | TPM_UNDEFINED, 133 | TPM_UNDEFINED, 134 | TPM_UNDEFINED, 135 | TPM_UNDEFINED, 136 | TPM_MEDIUM, /* 60 */ 137 | TPM_MEDIUM, 138 | TPM_MEDIUM, 139 | TPM_SHORT, 140 | TPM_SHORT, 141 | TPM_MEDIUM, /* 65 */ 142 | TPM_UNDEFINED, 143 | TPM_UNDEFINED, 144 | TPM_UNDEFINED, 145 | TPM_UNDEFINED, 146 | TPM_SHORT, /* 70 */ 147 | TPM_SHORT, 148 | TPM_UNDEFINED, 149 | TPM_UNDEFINED, 150 | TPM_UNDEFINED, 151 | TPM_UNDEFINED, /* 75 */ 152 | TPM_UNDEFINED, 153 | TPM_UNDEFINED, 154 | TPM_UNDEFINED, 155 | TPM_UNDEFINED, 156 | TPM_LONG, /* 80 */ 157 | TPM_UNDEFINED, 158 | TPM_MEDIUM, 159 | TPM_LONG, 160 | TPM_SHORT, 161 | TPM_UNDEFINED, /* 85 */ 162 | TPM_UNDEFINED, 163 | TPM_UNDEFINED, 164 | TPM_UNDEFINED, 165 | TPM_UNDEFINED, 166 | TPM_SHORT, /* 90 */ 167 | TPM_SHORT, 168 | TPM_SHORT, 169 | TPM_SHORT, 170 | TPM_SHORT, 171 | TPM_UNDEFINED, /* 95 */ 172 | TPM_UNDEFINED, 173 | TPM_UNDEFINED, 174 | TPM_UNDEFINED, 175 | TPM_UNDEFINED, 176 | TPM_MEDIUM, /* 100 */ 177 | TPM_SHORT, 178 | TPM_SHORT, 179 | TPM_UNDEFINED, 180 | TPM_UNDEFINED, 181 | TPM_UNDEFINED, /* 105 */ 182 | TPM_UNDEFINED, 183 | TPM_UNDEFINED, 184 | TPM_UNDEFINED, 185 | TPM_UNDEFINED, 186 | TPM_SHORT, /* 110 */ 187 | TPM_SHORT, 188 | TPM_SHORT, 189 | TPM_SHORT, 190 | TPM_SHORT, 191 | TPM_SHORT, /* 115 */ 192 | TPM_SHORT, 193 | TPM_SHORT, 194 | TPM_UNDEFINED, 195 | TPM_UNDEFINED, 196 | TPM_LONG, /* 120 */ 197 | TPM_LONG, 198 | TPM_MEDIUM, 199 | TPM_UNDEFINED, 200 | TPM_SHORT, 201 | TPM_SHORT, /* 125 */ 202 | TPM_SHORT, 203 | TPM_LONG, 204 | TPM_SHORT, 205 | TPM_SHORT, 206 | TPM_SHORT, /* 130 */ 207 | TPM_MEDIUM, 208 | TPM_UNDEFINED, 209 | TPM_SHORT, 210 | TPM_MEDIUM, 211 | TPM_UNDEFINED, /* 135 */ 212 | TPM_UNDEFINED, 213 | TPM_UNDEFINED, 214 | TPM_UNDEFINED, 215 | TPM_UNDEFINED, 216 | TPM_SHORT, /* 140 */ 217 | TPM_SHORT, 218 | TPM_UNDEFINED, 219 | TPM_UNDEFINED, 220 | TPM_UNDEFINED, 221 | TPM_UNDEFINED, /* 145 */ 222 | TPM_UNDEFINED, 223 | TPM_UNDEFINED, 224 | TPM_UNDEFINED, 225 | TPM_UNDEFINED, 226 | TPM_SHORT, /* 150 */ 227 | TPM_MEDIUM, 228 | TPM_MEDIUM, 229 | TPM_SHORT, 230 | TPM_SHORT, 231 | TPM_UNDEFINED, /* 155 */ 232 | TPM_UNDEFINED, 233 | TPM_UNDEFINED, 234 | TPM_UNDEFINED, 235 | TPM_UNDEFINED, 236 | TPM_SHORT, /* 160 */ 237 | TPM_SHORT, 238 | TPM_SHORT, 239 | TPM_SHORT, 240 | TPM_UNDEFINED, 241 | TPM_UNDEFINED, /* 165 */ 242 | TPM_UNDEFINED, 243 | TPM_UNDEFINED, 244 | TPM_UNDEFINED, 245 | TPM_UNDEFINED, 246 | TPM_LONG, /* 170 */ 247 | TPM_UNDEFINED, 248 | TPM_UNDEFINED, 249 | TPM_UNDEFINED, 250 | TPM_UNDEFINED, 251 | TPM_UNDEFINED, /* 175 */ 252 | TPM_UNDEFINED, 253 | TPM_UNDEFINED, 254 | TPM_UNDEFINED, 255 | TPM_UNDEFINED, 256 | TPM_MEDIUM, /* 180 */ 257 | TPM_SHORT, 258 | TPM_MEDIUM, 259 | TPM_MEDIUM, 260 | TPM_MEDIUM, 261 | TPM_MEDIUM, /* 185 */ 262 | TPM_SHORT, 263 | TPM_UNDEFINED, 264 | TPM_UNDEFINED, 265 | TPM_UNDEFINED, 266 | TPM_UNDEFINED, /* 190 */ 267 | TPM_UNDEFINED, 268 | TPM_UNDEFINED, 269 | TPM_UNDEFINED, 270 | TPM_UNDEFINED, 271 | TPM_UNDEFINED, /* 195 */ 272 | TPM_UNDEFINED, 273 | TPM_UNDEFINED, 274 | TPM_UNDEFINED, 275 | TPM_UNDEFINED, 276 | TPM_SHORT, /* 200 */ 277 | TPM_UNDEFINED, 278 | TPM_UNDEFINED, 279 | TPM_UNDEFINED, 280 | TPM_SHORT, 281 | TPM_SHORT, /* 205 */ 282 | TPM_SHORT, 283 | TPM_SHORT, 284 | TPM_SHORT, 285 | TPM_SHORT, 286 | TPM_MEDIUM, /* 210 */ 287 | TPM_UNDEFINED, 288 | TPM_MEDIUM, 289 | TPM_MEDIUM, 290 | TPM_MEDIUM, 291 | TPM_UNDEFINED, /* 215 */ 292 | TPM_MEDIUM, 293 | TPM_UNDEFINED, 294 | TPM_UNDEFINED, 295 | TPM_SHORT, 296 | TPM_SHORT, /* 220 */ 297 | TPM_SHORT, 298 | TPM_SHORT, 299 | TPM_SHORT, 300 | TPM_SHORT, 301 | TPM_UNDEFINED, /* 225 */ 302 | TPM_UNDEFINED, 303 | TPM_UNDEFINED, 304 | TPM_UNDEFINED, 305 | TPM_UNDEFINED, 306 | TPM_SHORT, /* 230 */ 307 | TPM_LONG, 308 | TPM_MEDIUM, 309 | TPM_UNDEFINED, 310 | TPM_UNDEFINED, 311 | TPM_UNDEFINED, /* 235 */ 312 | TPM_UNDEFINED, 313 | TPM_UNDEFINED, 314 | TPM_UNDEFINED, 315 | TPM_UNDEFINED, 316 | TPM_SHORT, /* 240 */ 317 | TPM_UNDEFINED, 318 | TPM_MEDIUM, 319 | }; 320 | 321 | /* 322 | * Returns max number of milliseconds to wait 323 | */ 324 | unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal) 325 | { 326 | int duration_idx = TPM_UNDEFINED; 327 | int duration = 0; 328 | 329 | if (ordinal < TPM_MAX_ORDINAL) 330 | duration_idx = tpm_ordinal_duration[ordinal]; 331 | else if ((ordinal & TPM_PROTECTED_ORDINAL_MASK) < 332 | TPM_MAX_PROTECTED_ORDINAL) 333 | duration_idx = 334 | tpm_protected_ordinal_duration[ordinal & 335 | TPM_PROTECTED_ORDINAL_MASK]; 336 | 337 | if (duration_idx != TPM_UNDEFINED) 338 | duration = chip->vendor.duration[duration_idx]; 339 | if (duration <= 0) 340 | return 2 * 60 * HZ; /*two minutes timeout*/ 341 | else 342 | return duration; 343 | } 344 | 345 | ssize_t tpm_transmit(const unsigned char *buf, size_t bufsiz) 346 | { 347 | ssize_t rc; 348 | u32 count, ordinal; 349 | unsigned long start, stop; 350 | 351 | struct tpm_chip *chip = &g_chip; 352 | 353 | /* switch endianess: big->little */ 354 | count = get_unaligned_be32(buf + TPM_CMD_SIZE_BYTE); 355 | ordinal = get_unaligned_be32(buf + TPM_CMD_ORDINAL_BYTE); 356 | 357 | if (count == 0) { 358 | dev_err(chip->dev, "no data\n"); 359 | return -ENODATA; 360 | } 361 | if (count > bufsiz) { 362 | dev_err(chip->dev, 363 | "invalid count value %x %zx\n", count, bufsiz); 364 | return -E2BIG; 365 | } 366 | 367 | rc = chip->vendor.send(chip, (u8 *) buf, count); 368 | if (rc < 0) { 369 | dev_err(chip->dev, "tpm_transmit: tpm_send: error %zd\n", rc); 370 | goto out; 371 | } 372 | 373 | if (chip->vendor.irq) 374 | goto out_recv; 375 | 376 | start = get_timer(0); 377 | stop = tpm_calc_ordinal_duration(chip, ordinal); 378 | do { 379 | dbg_printf("waiting for status...\n"); 380 | u8 status = chip->vendor.status(chip); 381 | if ((status & chip->vendor.req_complete_mask) == 382 | chip->vendor.req_complete_val) { 383 | dbg_printf("...got it;\n"); 384 | goto out_recv; 385 | } 386 | 387 | if ((status == chip->vendor.req_canceled)) { 388 | dev_err(chip->dev, "Operation Canceled\n"); 389 | rc = -ECANCELED; 390 | goto out; 391 | } 392 | msleep(TPM_TIMEOUT); 393 | } while (get_timer(start) < stop); 394 | 395 | chip->vendor.cancel(chip); 396 | dev_err(chip->dev, "Operation Timed out\n"); 397 | rc = -ETIME; 398 | goto out; 399 | 400 | out_recv: 401 | 402 | dbg_printf("out_recv: reading response...\n"); 403 | rc = chip->vendor.recv(chip, (u8 *) buf, TPM_BUFSIZE); 404 | if (rc < 0) 405 | dev_err(chip->dev, "tpm_transmit: tpm_recv: error %zd\n", rc); 406 | out: 407 | return rc; 408 | } 409 | 410 | enum tpm_capabilities { 411 | TPM_CAP_PROP = cpu_to_be32(5), 412 | }; 413 | 414 | enum tpm_sub_capabilities { 415 | TPM_CAP_PROP_TIS_TIMEOUT = cpu_to_be32(0x115), 416 | TPM_CAP_PROP_TIS_DURATION = cpu_to_be32(0x120), 417 | }; 418 | 419 | struct tpm_chip *tpm_register_hardware(const struct tpm_vendor_specific *entry) 420 | { 421 | struct tpm_chip *chip; 422 | 423 | /* Driver specific per-device data */ 424 | chip = &g_chip; 425 | memcpy(&chip->vendor, entry, sizeof(struct tpm_vendor_specific)); 426 | chip->is_open = 1; 427 | 428 | return chip; 429 | } 430 | 431 | int tpm_open(uint32_t dev_addr) 432 | { 433 | int rc; 434 | if (g_chip.is_open) 435 | return -EBUSY; 436 | rc = tpm_vendor_init(dev_addr); 437 | if (rc < 0) 438 | g_chip.is_open = 0; 439 | return rc; 440 | } 441 | 442 | void tpm_close(void) 443 | { 444 | if (g_chip.is_open) { 445 | tpm_vendor_cleanup(&g_chip); 446 | g_chip.is_open = 0; 447 | } 448 | } 449 | -------------------------------------------------------------------------------- /drivers/tpm/tpm.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Infineon Technologies 3 | * 4 | * Authors: 5 | * Peter Huewe 6 | * 7 | * Version: 2.1.1 8 | * 9 | * Description: 10 | * Device driver for TCG/TCPA TPM (trusted platform module). 11 | * Specifications at www.trustedcomputinggroup.org 12 | * 13 | * It is based on the Linux kernel driver tpm.c from Leendert van 14 | * Dorn, Dave Safford, Reiner Sailer, and Kyleen Hall. 15 | * 16 | * 17 | * See file CREDITS for list of people who contributed to this 18 | * project. 19 | * 20 | * This program is free software; you can redistribute it and/or 21 | * modify it under the terms of the GNU General Public License as 22 | * published by the Free Software Foundation, version 2 of the 23 | * License. 24 | * 25 | * This program is distributed in the hope that it will be useful, 26 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | * GNU General Public License for more details. 29 | * 30 | * You should have received a copy of the GNU General Public License 31 | * along with this program; if not, write to the Free Software 32 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 33 | * MA 02111-1307 USA 34 | */ 35 | 36 | #ifndef _TPM_H_ 37 | #define _TPM_H_ 38 | 39 | #include "compatibility.h" 40 | 41 | enum tpm_timeout { 42 | TPM_TIMEOUT = 5, /* msecs */ 43 | }; 44 | 45 | /* Size of external transmit buffer (used in tpm_transmit)*/ 46 | #define TPM_BUFSIZE 4096 47 | #define TPM_ERROR_SIZE 10 48 | #define TPM_HEADER_SIZE 10 49 | 50 | /* Index of fields in TPM command buffer */ 51 | #define TPM_CMD_SIZE_BYTE 2 52 | #define TPM_CMD_ORDINAL_BYTE 6 53 | 54 | /* Index of Count field in TPM response buffer */ 55 | #define TPM_RSP_SIZE_BYTE 2 56 | #define TPM_RSP_RC_BYTE 6 57 | 58 | struct tpm_chip; 59 | 60 | struct tpm_vendor_specific { 61 | const u8 req_complete_mask; 62 | const u8 req_complete_val; 63 | const u8 req_canceled; 64 | int irq; 65 | int (*recv) (struct tpm_chip *, u8 *, size_t); 66 | int (*send) (struct tpm_chip *, u8 *, size_t); 67 | void (*cancel) (struct tpm_chip *); 68 | u8 (*status) (struct tpm_chip *); 69 | int locality; 70 | unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* msec */ 71 | unsigned long duration[3]; /* msec */ 72 | }; 73 | 74 | struct tpm_chip { 75 | int is_open; 76 | struct tpm_vendor_specific vendor; 77 | /* testing */ 78 | u8 dev; 79 | }; 80 | 81 | struct tpm_input_header { 82 | __be16 tag; 83 | __be32 length; 84 | __be32 ordinal; 85 | } __attribute__ ((packed)); 86 | 87 | struct tpm_output_header { 88 | __be16 tag; 89 | __be32 length; 90 | __be32 return_code; 91 | } __attribute__ ((packed)); 92 | 93 | struct timeout_t { 94 | __be32 a; 95 | __be32 b; 96 | __be32 c; 97 | __be32 d; 98 | } __attribute__ ((packed)); 99 | 100 | struct duration_t { 101 | __be32 tpm_short; 102 | __be32 tpm_medium; 103 | __be32 tpm_long; 104 | } __attribute__ ((packed)); 105 | 106 | typedef union { 107 | struct timeout_t timeout; 108 | struct duration_t duration; 109 | } cap_t; 110 | 111 | struct tpm_getcap_params_in { 112 | __be32 cap; 113 | __be32 subcap_size; 114 | __be32 subcap; 115 | } __attribute__ ((packed)); 116 | 117 | struct tpm_getcap_params_out { 118 | __be32 cap_size; 119 | cap_t cap; 120 | } __attribute__ ((packed)); 121 | 122 | typedef union { 123 | struct tpm_input_header in; 124 | struct tpm_output_header out; 125 | } tpm_cmd_header; 126 | 127 | typedef union { 128 | struct tpm_getcap_params_out getcap_out; 129 | struct tpm_getcap_params_in getcap_in; 130 | } tpm_cmd_params; 131 | 132 | struct tpm_cmd_t { 133 | tpm_cmd_header header; 134 | tpm_cmd_params params; 135 | } __attribute__ ((packed)); 136 | 137 | 138 | /* ---------- Interface for TPM vendor ------------ */ 139 | 140 | extern struct tpm_chip *tpm_register_hardware( 141 | const struct tpm_vendor_specific *); 142 | 143 | extern int tpm_vendor_init(uint32_t dev_addr); 144 | 145 | extern void tpm_vendor_cleanup(struct tpm_chip *chip); 146 | 147 | /* ---------- Interface for TDDL ------------------- */ 148 | 149 | /* 150 | * if dev_addr != 0 - redefines TPM device address 151 | * Returns < 0 on error, 0 on success. 152 | */ 153 | extern int tpm_open(uint32_t dev_addr); 154 | 155 | extern void tpm_close(void); 156 | 157 | /* 158 | * Transmit bufsiz bytes out of buf to TPM and get results back in buf, too. 159 | * Returns < 0 on error, 0 on success. 160 | */ 161 | extern ssize_t tpm_transmit(const unsigned char *buf, size_t bufsiz); 162 | 163 | #endif 164 | -------------------------------------------------------------------------------- /drivers/tpm/tpm_i2c_atmel.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ATMEL I2C TPM AT97SC3204T 3 | * 4 | * Copyright (C) 2012 V Lab Technologies 5 | * 6 | * Authors: 7 | * Teddy Reed 8 | * 9 | * Device driver for TCG/TCPA TPM (trusted platform module). 10 | * Specifications at www.trustedcomputinggroup.org 11 | * 12 | * This device driver implements the TPM interface as defined in 13 | * the TCG TPM Interface Spec version 1.2. 14 | * 15 | * It is based on the AVR code in ATMEL's AT90USB128 TPM Development Board, 16 | * the Linux Infineon TIS 12C TPM driver from Peter Huewe, the original tpm_tis 17 | * device driver from Leendert van Dorn and Kyleen Hall, and code provided from 18 | * ATMEL's Application Group, Crypto Products Division and Max R. May. 19 | * 20 | * This program is free software; you can redistribute it and/or 21 | * modify it under the terms of the GNU General Public License as 22 | * published by the Free Software Foundation, version 2 of the 23 | * License. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #include "compatibility.h" 31 | #include "tpm.h" 32 | 33 | /** Found in AVR code and in Max's implementation **/ 34 | #ifdef TPM_BUFSIZE 35 | #undef TPM_BUFISZE 36 | #endif 37 | 38 | #define TPM_BUFSIZE 1024 39 | 40 | /* Atmel-defined I2C bus ID */ 41 | /* Note: this is defined in board configuration */ 42 | #ifndef CONFIG_TPM_I2C_ADDR 43 | #define CONFIG_TPM_I2C_ADDR 0x29 44 | #endif 45 | 46 | struct tpm_i2c_atmel_dev { 47 | uint addr; 48 | u8 buf[TPM_BUFSIZE]; 49 | /* chip struct is in tpm.c */ 50 | //struct tpm_chip *chip; 51 | }; 52 | 53 | static struct tpm_i2c_atmel_dev tpm_dev = { 54 | /* Note: replace with defined addr from board configuration */ 55 | .addr = CONFIG_TPM_I2C_ADDR 56 | }; 57 | 58 | static u8 tpm_i2c_read(u8 *buffer, size_t len); 59 | 60 | static void tpm_tis_i2c_ready (struct tpm_chip *chip); 61 | static u8 tpm_tis_i2c_status (struct tpm_chip *chip); 62 | static int tpm_tis_i2c_recv (struct tpm_chip *chip, u8 *buf, size_t count); 63 | static int tpm_tis_i2c_send (struct tpm_chip *chip, u8 *buf, size_t count); 64 | 65 | 66 | static u8 tpm_i2c_read(u8 *buffer, size_t len) 67 | { 68 | int rc; 69 | u32 trapdoor = 0; 70 | const u32 trapdoor_limit = 60000; /* not 5min with base 5mil seconds */ 71 | 72 | /** should lock the device **/ 73 | /** locking is hanging the I2C bus **/ 74 | //if (!tpm_dev.client->adapter->algo->master_xfer) 75 | // return -EOPNOTSUPP; 76 | //i2c_lock_adapter(tpm_dev.client->adapter); 77 | 78 | do { 79 | /* Atmel TPM requires RAW reads */ 80 | rc = i2c_read(tpm_dev.addr, 0, 0, buffer, len); 81 | if (rc == 0x00) /* successful read */ 82 | break; 83 | trapdoor++; 84 | msleep(5); 85 | } while (trapdoor < trapdoor_limit); /*trapdoor_limit*/ 86 | 87 | /** should unlock device **/ 88 | //i2c_unlock_adapter(tpm_dev.client->adapter); 89 | 90 | /** failed to read **/ 91 | if (trapdoor >= trapdoor_limit) 92 | return -EFAULT; 93 | 94 | return rc; 95 | } 96 | 97 | static int tpm_tis_i2c_recv (struct tpm_chip *chip, u8 *buf, size_t count) 98 | { 99 | int rc = 0; 100 | int expected; 101 | 102 | memset(tpm_dev.buf, 0x00, TPM_BUFSIZE); 103 | rc = tpm_i2c_read(tpm_dev.buf, TPM_HEADER_SIZE); /* returns status of read */ 104 | if (rc != 0x00) 105 | return rc; 106 | 107 | expected = tpm_dev.buf[4]; 108 | expected = expected << 8; 109 | expected += tpm_dev.buf[5]; /* should never be > TPM_BUFSIZE */ 110 | 111 | /* this should not happen, but just in case. */ 112 | if (expected > TPM_BUFSIZE) 113 | return -EIO; 114 | 115 | if (expected <= TPM_HEADER_SIZE) { 116 | /* finished here */ 117 | goto to_user; 118 | } 119 | 120 | /* Looks like it reads the entire expected, into the base of the buffer (from Max's code). 121 | * The AVR development board reads and additional expected - TPM_HEADER_SIZE. 122 | */ 123 | rc = tpm_i2c_read(tpm_dev.buf, expected); 124 | if (rc != 0x00) 125 | return rc; 126 | 127 | to_user: 128 | memcpy(buf, tpm_dev.buf, expected); 129 | 130 | return expected; 131 | } 132 | 133 | static int tpm_tis_i2c_send (struct tpm_chip *chip, u8 *buf, size_t count) 134 | { 135 | int rc; 136 | u8 tries, tries_limit = 2; 137 | 138 | /** should lock the device **/ 139 | /** locking is hanging the I2C bus **/ 140 | 141 | if (count > TPM_BUFSIZE) 142 | return -EINVAL; 143 | 144 | memset(tpm_dev.buf, 0x00, TPM_BUFSIZE); 145 | /* should add sanitization */ 146 | memcpy(tpm_dev.buf, buf, count); 147 | 148 | for (tries = 0; tries < tries_limit; tries++) { 149 | /* Atmel TPM uses RAW writes */ 150 | rc = i2c_write(tpm_dev.addr, 0, 0, tpm_dev.buf, count); 151 | if (rc == 0) 152 | break; /*win*/ 153 | udelay(60); 154 | } 155 | 156 | /** should unlock device **/ 157 | if (rc) { 158 | printf("tpm_i2c_atmel: write error\n"); 159 | return -EIO; 160 | } 161 | 162 | return count; 163 | } 164 | 165 | static u8 tpm_tis_i2c_status (struct tpm_chip *chip) 166 | { 167 | return 1; /* not a timeout */ 168 | } 169 | 170 | static void tpm_tis_i2c_ready (struct tpm_chip *chip) 171 | { 172 | /* nothing */ 173 | } 174 | 175 | 176 | static struct tpm_vendor_specific tpm_tis_i2c = { 177 | .status = tpm_tis_i2c_status, 178 | .recv = tpm_tis_i2c_recv, 179 | .send = tpm_tis_i2c_send, 180 | .cancel = tpm_tis_i2c_ready, 181 | /*.req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID, 182 | .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID, 183 | .req_canceled = TPM_STS_COMMAND_READY,*/ 184 | }; 185 | 186 | int tpm_vendor_init (uint32_t dev_addr) 187 | { 188 | uint old_addr; 189 | struct tpm_chip *chip; 190 | 191 | old_addr = tpm_dev.addr; 192 | if (dev_addr != 0) { 193 | tpm_dev.addr = dev_addr; 194 | } 195 | 196 | /* could call probe here */ 197 | 198 | chip = tpm_register_hardware(&tpm_tis_i2c); 199 | 200 | if (chip < 0) { 201 | tpm_dev.addr = old_addr; 202 | return -ENODEV; 203 | } 204 | 205 | /* Note: not sure why we set the irq to an int 206 | * This causes tpm_transmit to skip retries, waits, and interrupts 207 | */ 208 | chip->vendor.irq = 0; 209 | 210 | printf("1.2 TPM (atmel)\n"); 211 | 212 | return 0; 213 | } 214 | 215 | void tpm_vendor_cleanup(struct tpm_chip *chip) 216 | { 217 | /* nothing */ 218 | } 219 | -------------------------------------------------------------------------------- /drivers/tpm/tpm_i2c_infineon.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Infineon Technologies 3 | * 4 | * Authors: 5 | * Peter Huewe 6 | * 7 | * Description: 8 | * Device driver for TCG/TCPA TPM (trusted platform module). 9 | * Specifications at www.trustedcomputinggroup.org 10 | * 11 | * This device driver implements the TPM interface as defined in 12 | * the TCG TPM Interface Spec version 1.2, revision 1.0 and the 13 | * Infineon I2C Protocol Stack Specification v0.20. 14 | * 15 | * It is based on the Linux kernel driver tpm.c from Leendert van 16 | * Dorn, Dave Safford, Reiner Sailer, and Kyleen Hall. 17 | * 18 | * Version: 2.1.1 19 | * 20 | * See file CREDITS for list of people who contributed to this 21 | * project. 22 | * 23 | * This program is free software; you can redistribute it and/or 24 | * modify it under the terms of the GNU General Public License as 25 | * published by the Free Software Foundation, version 2 of the 26 | * License. 27 | * 28 | * This program is distributed in the hope that it will be useful, 29 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 30 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 31 | * GNU General Public License for more details. 32 | * 33 | * You should have received a copy of the GNU General Public License 34 | * along with this program; if not, write to the Free Software 35 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 36 | * MA 02111-1307 USA 37 | */ 38 | 39 | #include 40 | #include 41 | #include 42 | 43 | #include "compatibility.h" 44 | #include "tpm.h" 45 | 46 | /* max. buffer size supported by our tpm */ 47 | #ifdef TPM_BUFSIZE 48 | #undef TPM_BUFSIZE 49 | #endif 50 | #define TPM_BUFSIZE 1260 51 | /* Address of the TPM on the I2C bus */ 52 | #define TPM_I2C_ADDR 0x20 53 | /* max. number of iterations after i2c NAK */ 54 | #define MAX_COUNT 3 55 | 56 | #define SLEEP_DURATION 60 /*in usec*/ 57 | 58 | /* max. number of iterations after i2c NAK for 'long' commands 59 | * we need this especially for sending TPM_READY, since the cleanup after the 60 | * transtion to the ready state may take some time, but it is unpredictable 61 | * how long it will take. 62 | */ 63 | #define MAX_COUNT_LONG 50 64 | 65 | #define SLEEP_DURATION_LONG 210 /* in usec */ 66 | 67 | /* expected value for DIDVID register */ 68 | #define TPM_TIS_I2C_DID_VID 0x000b15d1L 69 | 70 | /* Structure to store I2C TPM specific stuff */ 71 | struct tpm_inf_dev { 72 | uint addr; 73 | u8 buf[TPM_BUFSIZE + sizeof(u8)]; /* max. buffer size + addr */ 74 | }; 75 | 76 | static struct tpm_inf_dev tpm_dev = { 77 | .addr = TPM_I2C_ADDR 78 | }; 79 | 80 | /* 81 | * iic_tpm_read() - read from TPM register 82 | * @addr: register address to read from 83 | * @buffer: provided by caller 84 | * @len: number of bytes to read 85 | * 86 | * Read len bytes from TPM register and put them into 87 | * buffer (little-endian format, i.e. first byte is put into buffer[0]). 88 | * 89 | * NOTE: TPM is big-endian for multi-byte values. Multi-byte 90 | * values have to be swapped. 91 | * 92 | * Return -EIO on error, 0 on success. 93 | */ 94 | int iic_tpm_read(u8 addr, u8 *buffer, size_t len) 95 | { 96 | int rc; 97 | int count; 98 | uint myaddr = addr; 99 | /* we have to use uint here, uchar hangs the board */ 100 | 101 | for (count = 0; count < MAX_COUNT; count++) { 102 | rc = i2c_write(tpm_dev.addr, 0, 0, (uchar *) &myaddr, 1); 103 | if (rc == 0) 104 | break; /*success, break to skip sleep*/ 105 | 106 | udelay(SLEEP_DURATION); 107 | } 108 | 109 | if (rc) 110 | return -rc; 111 | 112 | /* After the TPM has successfully received the register address it needs 113 | * some time, thus we're sleeping here again, before retrieving the data 114 | */ 115 | for (count = 0; count < MAX_COUNT; count++) { 116 | udelay(SLEEP_DURATION); 117 | rc = i2c_read(tpm_dev.addr, 0, 0, buffer, len); 118 | if (rc == 0) 119 | break; /*success, break to skip sleep*/ 120 | 121 | } 122 | 123 | if (rc) 124 | return -rc; 125 | 126 | return 0; 127 | } 128 | 129 | static int iic_tpm_write_generic(u8 addr, u8 *buffer, size_t len, 130 | unsigned int sleep_time, 131 | u8 max_count) 132 | { 133 | int rc = 0; 134 | int count; 135 | 136 | /* prepare send buffer */ 137 | tpm_dev.buf[0] = addr; 138 | memcpy(&(tpm_dev.buf[1]), buffer, len); 139 | 140 | for (count = 0; count < max_count; count++) { 141 | rc = i2c_write(tpm_dev.addr, 0, 0, tpm_dev.buf, len + 1); 142 | if (rc == 0) 143 | break; /*success, break to skip sleep*/ 144 | 145 | udelay(sleep_time); 146 | } 147 | 148 | if (rc) 149 | return -rc; 150 | 151 | return 0; 152 | } 153 | 154 | /* 155 | * iic_tpm_write() - write to TPM register 156 | * @addr: register address to write to 157 | * @buffer: containing data to be written 158 | * @len: number of bytes to write 159 | * 160 | * Write len bytes from provided buffer to TPM register (little 161 | * endian format, i.e. buffer[0] is written as first byte). 162 | * 163 | * NOTE: TPM is big-endian for multi-byte values. Multi-byte 164 | * values have to be swapped. 165 | * 166 | * NOTE: use this function instead of the iic_tpm_write_generic function. 167 | * 168 | * Return -EIO on error, 0 on success 169 | */ 170 | static int iic_tpm_write(u8 addr, u8 *buffer, size_t len) 171 | { 172 | return iic_tpm_write_generic(addr, buffer, len, SLEEP_DURATION, 173 | MAX_COUNT); 174 | } 175 | 176 | /* 177 | * This function is needed especially for the cleanup situation after 178 | * sending TPM_READY 179 | * */ 180 | static int iic_tpm_write_long(u8 addr, u8 *buffer, size_t len) 181 | { 182 | return iic_tpm_write_generic(addr, buffer, len, SLEEP_DURATION_LONG, 183 | MAX_COUNT_LONG); 184 | } 185 | 186 | enum tis_access { 187 | TPM_ACCESS_VALID = 0x80, 188 | TPM_ACCESS_ACTIVE_LOCALITY = 0x20, 189 | TPM_ACCESS_REQUEST_PENDING = 0x04, 190 | TPM_ACCESS_REQUEST_USE = 0x02, 191 | }; 192 | 193 | enum tis_status { 194 | TPM_STS_VALID = 0x80, 195 | TPM_STS_COMMAND_READY = 0x40, 196 | TPM_STS_GO = 0x20, 197 | TPM_STS_DATA_AVAIL = 0x10, 198 | TPM_STS_DATA_EXPECT = 0x08, 199 | }; 200 | 201 | enum tis_defaults { 202 | TIS_SHORT_TIMEOUT = 750, /* ms */ 203 | TIS_LONG_TIMEOUT = 2000, /* 2 sec */ 204 | }; 205 | 206 | #define TPM_ACCESS(l) (0x0000 | ((l) << 4)) 207 | #define TPM_STS(l) (0x0001 | ((l) << 4)) 208 | #define TPM_DATA_FIFO(l) (0x0005 | ((l) << 4)) 209 | #define TPM_DID_VID(l) (0x0006 | ((l) << 4)) 210 | 211 | static int check_locality(struct tpm_chip *chip, int loc) 212 | { 213 | u8 buf; 214 | int rc; 215 | 216 | rc = iic_tpm_read(TPM_ACCESS(loc), &buf, 1); 217 | if (rc < 0) 218 | return rc; 219 | 220 | if ((buf & (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) == 221 | (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) { 222 | chip->vendor.locality = loc; 223 | return loc; 224 | } 225 | 226 | return -1; 227 | } 228 | 229 | static void release_locality(struct tpm_chip *chip, int loc, int force) 230 | { 231 | u8 buf; 232 | if (iic_tpm_read(TPM_ACCESS(loc), &buf, 1) < 0) 233 | return; 234 | 235 | if (force || (buf & (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) == 236 | (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) { 237 | buf = TPM_ACCESS_ACTIVE_LOCALITY; 238 | iic_tpm_write(TPM_ACCESS(loc), &buf, 1); 239 | } 240 | } 241 | 242 | static int request_locality(struct tpm_chip *chip, int loc) 243 | { 244 | unsigned long start, stop; 245 | u8 buf = TPM_ACCESS_REQUEST_USE; 246 | 247 | if (check_locality(chip, loc) >= 0) 248 | return loc; /* we already have the locality */ 249 | 250 | iic_tpm_write(TPM_ACCESS(loc), &buf, 1); 251 | 252 | /* wait for burstcount */ 253 | start = get_timer(0); 254 | stop = chip->vendor.timeout_a; 255 | do { 256 | if (check_locality(chip, loc) >= 0) 257 | return loc; 258 | msleep(TPM_TIMEOUT); 259 | } while (get_timer(start) < stop); 260 | 261 | return -1; 262 | } 263 | 264 | static u8 tpm_tis_i2c_status(struct tpm_chip *chip) 265 | { 266 | /* NOTE: since i2c read may fail, return 0 in this case --> time-out */ 267 | u8 buf; 268 | if (iic_tpm_read(TPM_STS(chip->vendor.locality), &buf, 1) < 0) 269 | return 0; 270 | else 271 | return buf; 272 | } 273 | 274 | static void tpm_tis_i2c_ready(struct tpm_chip *chip) 275 | { 276 | /* this causes the current command to be aborted */ 277 | u8 buf = TPM_STS_COMMAND_READY; 278 | iic_tpm_write_long(TPM_STS(chip->vendor.locality), &buf, 1); 279 | } 280 | 281 | static ssize_t get_burstcount(struct tpm_chip *chip) 282 | { 283 | unsigned long start, stop; 284 | ssize_t burstcnt; 285 | u8 buf[3]; 286 | 287 | /* wait for burstcount */ 288 | /* which timeout value, spec has 2 answers (c & d) */ 289 | start = get_timer(0); 290 | stop = chip->vendor.timeout_d; 291 | do { 292 | /* Note: STS is little endian */ 293 | if (iic_tpm_read(TPM_STS(chip->vendor.locality) + 1, buf, 3) < 0) 294 | burstcnt = 0; 295 | else 296 | burstcnt = (buf[2] << 16) + (buf[1] << 8) + buf[0]; 297 | 298 | if (burstcnt) 299 | return burstcnt; 300 | msleep(TPM_TIMEOUT); 301 | } while (get_timer(start) < stop); 302 | return -EBUSY; 303 | } 304 | 305 | static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, 306 | int *status) 307 | { 308 | unsigned long start, stop; 309 | 310 | /* check current status */ 311 | *status = tpm_tis_i2c_status(chip); 312 | if ((*status & mask) == mask) 313 | return 0; 314 | 315 | start = get_timer(0); 316 | stop = timeout; 317 | do { 318 | msleep(TPM_TIMEOUT); 319 | *status = tpm_tis_i2c_status(chip); 320 | if ((*status & mask) == mask) 321 | return 0; 322 | 323 | } while (get_timer(start) < stop); 324 | 325 | return -ETIME; 326 | } 327 | 328 | static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) 329 | { 330 | size_t size = 0; 331 | ssize_t burstcnt; 332 | int rc; 333 | 334 | while (size < count) { 335 | burstcnt = get_burstcount(chip); 336 | 337 | /* burstcount < 0 = tpm is busy */ 338 | if (burstcnt < 0) 339 | return burstcnt; 340 | 341 | /* limit received data to max. left */ 342 | if (burstcnt > (count - size)) 343 | burstcnt = count - size; 344 | 345 | rc = iic_tpm_read(TPM_DATA_FIFO(chip->vendor.locality), 346 | &(buf[size]), 347 | burstcnt); 348 | if (rc == 0) 349 | size += burstcnt; 350 | 351 | } 352 | return size; 353 | } 354 | 355 | static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count) 356 | { 357 | int size = 0; 358 | int expected, status; 359 | 360 | if (count < TPM_HEADER_SIZE) { 361 | size = -EIO; 362 | goto out; 363 | } 364 | 365 | /* read first 10 bytes, including tag, paramsize, and result */ 366 | size = recv_data(chip, buf, TPM_HEADER_SIZE); 367 | if (size < TPM_HEADER_SIZE) { 368 | dev_err(chip->dev, "Unable to read header\n"); 369 | goto out; 370 | } 371 | 372 | expected = get_unaligned_be32(buf + TPM_RSP_SIZE_BYTE); 373 | if ((size_t)expected > count) { 374 | size = -EIO; 375 | goto out; 376 | } 377 | 378 | size += recv_data(chip, &buf[TPM_HEADER_SIZE], 379 | expected - TPM_HEADER_SIZE); 380 | if (size < expected) { 381 | dev_err(chip->dev, "Unable to read remainder of result\n"); 382 | size = -ETIME; 383 | goto out; 384 | } 385 | 386 | wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status); 387 | if (status & TPM_STS_DATA_AVAIL) { /* retry? */ 388 | dev_err(chip->dev, "Error left over data\n"); 389 | size = -EIO; 390 | goto out; 391 | } 392 | 393 | out: 394 | tpm_tis_i2c_ready(chip); 395 | /* The TPM needs some time to clean up here, 396 | * so we sleep rather than keeping the bus busy 397 | */ 398 | msleep(2); 399 | release_locality(chip, chip->vendor.locality, 0); 400 | 401 | return size; 402 | } 403 | 404 | static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) 405 | { 406 | int rc, status; 407 | ssize_t burstcnt; 408 | size_t count = 0; 409 | u8 sts = TPM_STS_GO; 410 | 411 | if (len > TPM_BUFSIZE) 412 | return -E2BIG; /* command is too long for our tpm, sorry */ 413 | 414 | if (request_locality(chip, 0) < 0) 415 | return -EBUSY; 416 | 417 | status = tpm_tis_i2c_status(chip); 418 | if ((status & TPM_STS_COMMAND_READY) == 0) { 419 | tpm_tis_i2c_ready(chip); 420 | if (wait_for_stat 421 | (chip, TPM_STS_COMMAND_READY, 422 | chip->vendor.timeout_b, &status) < 0) { 423 | rc = -ETIME; 424 | goto out_err; 425 | } 426 | } 427 | 428 | while (count < len - 1) { 429 | burstcnt = get_burstcount(chip); 430 | 431 | /* burstcount < 0 = tpm is busy */ 432 | if (burstcnt < 0) 433 | return burstcnt; 434 | 435 | if (burstcnt > (len-1-count)) 436 | burstcnt = len-1-count; 437 | 438 | #ifdef CONFIG_TPM_I2C_BURST_LIMITATION 439 | if (burstcnt > CONFIG_TPM_I2C_BURST_LIMITATION) 440 | burstcnt = CONFIG_TPM_I2C_BURST_LIMITATION; 441 | #endif /* CONFIG_TPM_I2C_BURST_LIMITATION */ 442 | 443 | rc = iic_tpm_write(TPM_DATA_FIFO(chip->vendor.locality), 444 | &(buf[count]), burstcnt); 445 | if (rc == 0) 446 | count += burstcnt; 447 | 448 | wait_for_stat(chip, TPM_STS_VALID, 449 | chip->vendor.timeout_c, &status); 450 | 451 | if ((status & TPM_STS_DATA_EXPECT) == 0) { 452 | rc = -EIO; 453 | goto out_err; 454 | } 455 | 456 | } 457 | 458 | /* write last byte */ 459 | iic_tpm_write(TPM_DATA_FIFO(chip->vendor.locality), &(buf[count]), 1); 460 | wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status); 461 | if ((status & TPM_STS_DATA_EXPECT) != 0) { 462 | rc = -EIO; 463 | goto out_err; 464 | } 465 | 466 | /* go and do it */ 467 | iic_tpm_write(TPM_STS(chip->vendor.locality), &sts, 1); 468 | 469 | return len; 470 | out_err: 471 | tpm_tis_i2c_ready(chip); 472 | /* The TPM needs some time to clean up here, 473 | * so we sleep rather than keeping the bus busy 474 | */ 475 | msleep(2); 476 | release_locality(chip, chip->vendor.locality, 0); 477 | 478 | return rc; 479 | } 480 | 481 | static struct tpm_vendor_specific tpm_tis_i2c = { 482 | .status = tpm_tis_i2c_status, 483 | .recv = tpm_tis_i2c_recv, 484 | .send = tpm_tis_i2c_send, 485 | .cancel = tpm_tis_i2c_ready, 486 | .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID, 487 | .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID, 488 | .req_canceled = TPM_STS_COMMAND_READY, 489 | }; 490 | 491 | /* initialisation of i2c tpm */ 492 | 493 | 494 | int tpm_vendor_init(uint32_t dev_addr) 495 | { 496 | u32 vendor; 497 | uint old_addr; 498 | int rc = 0; 499 | struct tpm_chip *chip; 500 | 501 | old_addr = tpm_dev.addr; 502 | if (dev_addr != 0) 503 | tpm_dev.addr = dev_addr; 504 | 505 | chip = tpm_register_hardware(&tpm_tis_i2c); 506 | if (chip < 0) { 507 | rc = -ENODEV; 508 | goto out_err; 509 | } 510 | 511 | /* Disable interrupts (not supported) */ 512 | chip->vendor.irq = 0; 513 | 514 | /* Default timeouts */ 515 | chip->vendor.timeout_a = TIS_SHORT_TIMEOUT; 516 | chip->vendor.timeout_b = TIS_LONG_TIMEOUT; 517 | chip->vendor.timeout_c = TIS_SHORT_TIMEOUT; 518 | chip->vendor.timeout_d = TIS_SHORT_TIMEOUT; 519 | 520 | if (request_locality(chip, 0) != 0) { 521 | rc = -ENODEV; 522 | goto out_err; 523 | } 524 | 525 | /* read four bytes from DID_VID register */ 526 | if (iic_tpm_read(TPM_DID_VID(0), (uchar *)&vendor, 4) < 0) { 527 | rc = -EIO; 528 | goto out_release; 529 | } 530 | 531 | /* create DID_VID register value, after swapping to little-endian */ 532 | vendor = be32_to_cpu(vendor); 533 | 534 | if (vendor != TPM_TIS_I2C_DID_VID) { 535 | rc = -ENODEV; 536 | goto out_release; 537 | } 538 | 539 | dev_info(dev, "1.2 TPM (device-id 0x%X)\n", vendor >> 16); 540 | 541 | /* 542 | * A timeout query to TPM can be placed here. 543 | * Standard timeout values are used so far 544 | */ 545 | 546 | return 0; 547 | 548 | out_release: 549 | release_locality(chip, 0, 1); 550 | 551 | out_err: 552 | tpm_dev.addr = old_addr; 553 | return rc; 554 | } 555 | 556 | void tpm_vendor_cleanup(struct tpm_chip *chip) 557 | { 558 | release_locality(chip, chip->vendor.locality, 1); 559 | } 560 | -------------------------------------------------------------------------------- /drivers/tpm/tpm_lpc_generic.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 The Chromium OS Authors. 3 | * 4 | * See file CREDITS for list of people who contributed to this 5 | * project. 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of 10 | * the License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 20 | * MA 02111-1307 USA 21 | */ 22 | 23 | /* 24 | * The code in this file is based on the article "Writing a TPM Device Driver" 25 | * published on http://ptgmedia.pearsoncmg.com. 26 | * 27 | * One principal difference is that in the simplest config the other than 0 28 | * TPM localities do not get mapped by some devices (for instance, by Infineon 29 | * slb9635), so this driver provides access to locality 0 only. 30 | */ 31 | 32 | #include 33 | #include 34 | #include 35 | 36 | #define PREFIX "lpc_tpm: " 37 | 38 | struct tpm_locality { 39 | u32 access; 40 | u8 padding0[4]; 41 | u32 int_enable; 42 | u8 vector; 43 | u8 padding1[3]; 44 | u32 int_status; 45 | u32 int_capability; 46 | u32 tpm_status; 47 | u8 padding2[8]; 48 | u8 data; 49 | u8 padding3[3803]; 50 | u32 did_vid; 51 | u8 rid; 52 | u8 padding4[251]; 53 | }; 54 | 55 | /* 56 | * This pointer refers to the TPM chip, 5 of its localities are mapped as an 57 | * array. 58 | */ 59 | #define TPM_TOTAL_LOCALITIES 5 60 | static struct tpm_locality *lpc_tpm_dev = 61 | (struct tpm_locality *)CONFIG_TPM_TIS_BASE_ADDRESS; 62 | 63 | /* Some registers' bit field definitions */ 64 | #define TIS_STS_VALID (1 << 7) /* 0x80 */ 65 | #define TIS_STS_COMMAND_READY (1 << 6) /* 0x40 */ 66 | #define TIS_STS_TPM_GO (1 << 5) /* 0x20 */ 67 | #define TIS_STS_DATA_AVAILABLE (1 << 4) /* 0x10 */ 68 | #define TIS_STS_EXPECT (1 << 3) /* 0x08 */ 69 | #define TIS_STS_RESPONSE_RETRY (1 << 1) /* 0x02 */ 70 | 71 | #define TIS_ACCESS_TPM_REG_VALID_STS (1 << 7) /* 0x80 */ 72 | #define TIS_ACCESS_ACTIVE_LOCALITY (1 << 5) /* 0x20 */ 73 | #define TIS_ACCESS_BEEN_SEIZED (1 << 4) /* 0x10 */ 74 | #define TIS_ACCESS_SEIZE (1 << 3) /* 0x08 */ 75 | #define TIS_ACCESS_PENDING_REQUEST (1 << 2) /* 0x04 */ 76 | #define TIS_ACCESS_REQUEST_USE (1 << 1) /* 0x02 */ 77 | #define TIS_ACCESS_TPM_ESTABLISHMENT (1 << 0) /* 0x01 */ 78 | 79 | #define TIS_STS_BURST_COUNT_MASK (0xffff) 80 | #define TIS_STS_BURST_COUNT_SHIFT (8) 81 | 82 | /* 83 | * Error value returned if a tpm register does not enter the expected state 84 | * after continuous polling. No actual TPM register reading ever returns -1, 85 | * so this value is a safe error indication to be mixed with possible status 86 | * register values. 87 | */ 88 | #define TPM_TIMEOUT_ERR (-1) 89 | 90 | /* Error value returned on various TPM driver errors. */ 91 | #define TPM_DRIVER_ERR (1) 92 | 93 | /* 1 second is plenty for anything TPM does. */ 94 | #define MAX_DELAY_US (1000 * 1000) 95 | 96 | /* Retrieve burst count value out of the status register contents. */ 97 | static u16 burst_count(u32 status) 98 | { 99 | return (status >> TIS_STS_BURST_COUNT_SHIFT) & TIS_STS_BURST_COUNT_MASK; 100 | } 101 | 102 | /* 103 | * Structures defined below allow creating descriptions of TPM vendor/device 104 | * ID information for run time discovery. The only device the system knows 105 | * about at this time is Infineon slb9635. 106 | */ 107 | struct device_name { 108 | u16 dev_id; 109 | const char * const dev_name; 110 | }; 111 | 112 | struct vendor_name { 113 | u16 vendor_id; 114 | const char *vendor_name; 115 | const struct device_name *dev_names; 116 | }; 117 | 118 | static struct device_name atmel_devices[] = { 119 | {0x3204, "AT97SC3204"}, 120 | {0xffff} 121 | }; 122 | 123 | static struct device_name infineon_devices[] = { 124 | {0x000b, "SLB9635 TT 1.2"}, 125 | {0xffff} 126 | }; 127 | 128 | static struct device_name nuvoton_devices[] = { 129 | {0x00fe, "NPCT420AA V2"}, 130 | {0xffff} 131 | }; 132 | 133 | static struct device_name stmicro_devices[] = { 134 | {0x0000, "ST33ZP24" }, 135 | {0xffff} 136 | }; 137 | 138 | static const struct vendor_name vendor_names[] = { 139 | {0x1114, "Atmel", atmel_devices}, 140 | {0x15d1, "Infineon", infineon_devices}, 141 | {0x1050, "Nuvoton", nuvoton_devices}, 142 | {0x104a, "ST Microelectronics", stmicro_devices}, 143 | }; 144 | 145 | /* 146 | * Cached vendor/device ID pair to indicate that the device has been already 147 | * discovered. 148 | */ 149 | static u32 vendor_dev_id; 150 | 151 | /* TPM access wrappers to support tracing */ 152 | static u8 tpm_read_byte(const u8 *ptr) 153 | { 154 | u8 ret = readb(ptr); 155 | debug(PREFIX "Read reg 0x%4.4x returns 0x%2.2x\n", 156 | (u32)(uintptr_t)ptr - (u32)(uintptr_t)lpc_tpm_dev, ret); 157 | return ret; 158 | } 159 | 160 | static u32 tpm_read_word(const u32 *ptr) 161 | { 162 | u32 ret = readl(ptr); 163 | debug(PREFIX "Read reg 0x%4.4x returns 0x%8.8x\n", 164 | (u32)(uintptr_t)ptr - (u32)(uintptr_t)lpc_tpm_dev, ret); 165 | return ret; 166 | } 167 | 168 | static void tpm_write_byte(u8 value, u8 *ptr) 169 | { 170 | debug(PREFIX "Write reg 0x%4.4x with 0x%2.2x\n", 171 | (u32)(uintptr_t)ptr - (u32)(uintptr_t)lpc_tpm_dev, value); 172 | writeb(value, ptr); 173 | } 174 | 175 | static void tpm_write_word(u32 value, u32 *ptr) 176 | { 177 | debug(PREFIX "Write reg 0x%4.4x with 0x%8.8x\n", 178 | (u32)(uintptr_t)ptr - (u32)(uintptr_t)lpc_tpm_dev, value); 179 | writel(value, ptr); 180 | } 181 | 182 | /* 183 | * tis_wait_reg() 184 | * 185 | * Wait for at least a second for a register to change its state to match the 186 | * expected state. Normally the transition happens within microseconds. 187 | * 188 | * @reg - pointer to the TPM register 189 | * @mask - bitmask for the bitfield(s) to watch 190 | * @expected - value the field(s) are supposed to be set to 191 | * 192 | * Returns the register contents in case the expected value was found in the 193 | * appropriate register bits, or TPM_TIMEOUT_ERR on timeout. 194 | */ 195 | static u32 tis_wait_reg(u32 *reg, u8 mask, u8 expected) 196 | { 197 | u32 time_us = MAX_DELAY_US; 198 | 199 | while (time_us > 0) { 200 | u32 value = tpm_read_word(reg); 201 | if ((value & mask) == expected) 202 | return value; 203 | udelay(1); /* 1 us */ 204 | time_us--; 205 | } 206 | return TPM_TIMEOUT_ERR; 207 | } 208 | 209 | /* 210 | * Probe the TPM device and try determining its manufacturer/device name. 211 | * 212 | * Returns 0 on success (the device is found or was found during an earlier 213 | * invocation) or TPM_DRIVER_ERR if the device is not found. 214 | */ 215 | int tis_init(void) 216 | { 217 | u32 didvid; 218 | int i; 219 | const char *device_name = "unknown"; 220 | const char *vendor_name = device_name; 221 | const struct device_name *dev; 222 | u16 vid, did; 223 | 224 | if (vendor_dev_id) 225 | return 0; /* Already probed. */ 226 | 227 | didvid = tpm_read_word(&lpc_tpm_dev[0].did_vid); 228 | if (!didvid || (didvid == 0xffffffff)) { 229 | printf("%s: No TPM device found\n", __func__); 230 | return TPM_DRIVER_ERR; 231 | } 232 | 233 | vendor_dev_id = didvid; 234 | 235 | vid = didvid & 0xffff; 236 | did = (didvid >> 16) & 0xffff; 237 | for (i = 0; i < ARRAY_SIZE(vendor_names); i++) { 238 | int j = 0; 239 | u16 known_did; 240 | 241 | if (vid == vendor_names[i].vendor_id) 242 | vendor_name = vendor_names[i].vendor_name; 243 | else 244 | continue; 245 | 246 | dev = &vendor_names[i].dev_names[j]; 247 | while ((known_did = dev->dev_id) != 0xffff) { 248 | if (known_did == did) { 249 | device_name = dev->dev_name; 250 | break; 251 | } 252 | j++; 253 | } 254 | break; 255 | } 256 | 257 | printf("Found TPM %s by %s\n", device_name, vendor_name); 258 | return 0; 259 | } 260 | 261 | /* 262 | * PC Client Specific TPM Interface Specification section 11.2.12: 263 | * 264 | * Software must be prepared to send two writes of a "1" to command ready 265 | * field: the first to indicate successful read of all the data, thus 266 | * clearing the data from the ReadFIFO and freeing the TPM's resources, 267 | * and the second to indicate to the TPM it is about to send a new command. 268 | * 269 | * In practice not all TPMs behave the same so it is necessary to be 270 | * flexible when trying to set command ready. 271 | * 272 | * Returns 0 on success if the TPM is ready for transactions. 273 | * Returns TPM_TIMEOUT_ERR if the command ready bit does not get set. 274 | */ 275 | static int tis_command_ready(u8 locality) 276 | { 277 | u32 status; 278 | 279 | /* 1st attempt to set command ready */ 280 | tpm_write_word(TIS_STS_COMMAND_READY, 281 | &lpc_tpm_dev[locality].tpm_status); 282 | 283 | /* Wait for response */ 284 | status = tpm_read_word(&lpc_tpm_dev[locality].tpm_status); 285 | 286 | /* Check if command ready is set yet */ 287 | if (status & TIS_STS_COMMAND_READY) 288 | return 0; 289 | 290 | /* 2nd attempt to set command ready */ 291 | tpm_write_word(TIS_STS_COMMAND_READY, 292 | &lpc_tpm_dev[locality].tpm_status); 293 | 294 | /* Wait for command ready to get set */ 295 | status = tis_wait_reg(&lpc_tpm_dev[locality].tpm_status, 296 | TIS_STS_COMMAND_READY, TIS_STS_COMMAND_READY); 297 | 298 | return (status == TPM_TIMEOUT_ERR) ? TPM_TIMEOUT_ERR : 0; 299 | } 300 | 301 | /* 302 | * tis_senddata() 303 | * 304 | * send the passed in data to the TPM device. 305 | * 306 | * @data - address of the data to send, byte by byte 307 | * @len - length of the data to send 308 | * 309 | * Returns 0 on success, TPM_DRIVER_ERR on error (in case the device does 310 | * not accept the entire command). 311 | */ 312 | static u32 tis_senddata(const u8 * const data, u32 len) 313 | { 314 | u32 offset = 0; 315 | u16 burst = 0; 316 | u32 max_cycles = 0; 317 | u8 locality = 0; 318 | u32 value; 319 | 320 | value = tis_wait_reg(&lpc_tpm_dev[locality].tpm_status, 321 | TIS_STS_COMMAND_READY, TIS_STS_COMMAND_READY); 322 | if (value == TPM_TIMEOUT_ERR) { 323 | printf("%s:%d - failed to get 'command_ready' status\n", 324 | __FILE__, __LINE__); 325 | return TPM_DRIVER_ERR; 326 | } 327 | burst = burst_count(value); 328 | 329 | while (1) { 330 | unsigned count; 331 | 332 | /* Wait till the device is ready to accept more data. */ 333 | while (!burst) { 334 | if (max_cycles++ == MAX_DELAY_US) { 335 | printf("%s:%d failed to feed %d bytes of %d\n", 336 | __FILE__, __LINE__, len - offset, len); 337 | return TPM_DRIVER_ERR; 338 | } 339 | udelay(1); 340 | burst = burst_count(tpm_read_word(&lpc_tpm_dev 341 | [locality].tpm_status)); 342 | } 343 | 344 | max_cycles = 0; 345 | 346 | /* 347 | * Calculate number of bytes the TPM is ready to accept in one 348 | * shot. 349 | * 350 | * We want to send the last byte outside of the loop (hence 351 | * the -1 below) to make sure that the 'expected' status bit 352 | * changes to zero exactly after the last byte is fed into the 353 | * FIFO. 354 | */ 355 | count = min(burst, len - offset - 1); 356 | while (count--) 357 | tpm_write_byte(data[offset++], 358 | &lpc_tpm_dev[locality].data); 359 | 360 | value = tis_wait_reg(&lpc_tpm_dev[locality].tpm_status, 361 | TIS_STS_VALID, TIS_STS_VALID); 362 | 363 | if ((value == TPM_TIMEOUT_ERR) || !(value & TIS_STS_EXPECT)) { 364 | printf("%s:%d TPM command feed overflow\n", 365 | __FILE__, __LINE__); 366 | return TPM_DRIVER_ERR; 367 | } 368 | 369 | burst = burst_count(value); 370 | if ((offset == (len - 1)) && burst) { 371 | /* 372 | * We need to be able to send the last byte to the 373 | * device, so burst size must be nonzero before we 374 | * break out. 375 | */ 376 | break; 377 | } 378 | } 379 | 380 | /* Send the last byte. */ 381 | tpm_write_byte(data[offset++], &lpc_tpm_dev[locality].data); 382 | /* 383 | * Verify that TPM does not expect any more data as part of this 384 | * command. 385 | */ 386 | value = tis_wait_reg(&lpc_tpm_dev[locality].tpm_status, 387 | TIS_STS_VALID, TIS_STS_VALID); 388 | if ((value == TPM_TIMEOUT_ERR) || (value & TIS_STS_EXPECT)) { 389 | printf("%s:%d unexpected TPM status 0x%x\n", 390 | __FILE__, __LINE__, value); 391 | return TPM_DRIVER_ERR; 392 | } 393 | 394 | /* OK, sitting pretty, let's start the command execution. */ 395 | tpm_write_word(TIS_STS_TPM_GO, &lpc_tpm_dev[locality].tpm_status); 396 | return 0; 397 | } 398 | 399 | /* 400 | * tis_readresponse() 401 | * 402 | * read the TPM device response after a command was issued. 403 | * 404 | * @buffer - address where to read the response, byte by byte. 405 | * @len - pointer to the size of buffer 406 | * 407 | * On success stores the number of received bytes to len and returns 0. On 408 | * errors (misformatted TPM data or synchronization problems) returns 409 | * TPM_DRIVER_ERR. 410 | */ 411 | static u32 tis_readresponse(u8 *buffer, u32 *len) 412 | { 413 | u16 burst; 414 | u32 value; 415 | u32 offset = 0; 416 | u8 locality = 0; 417 | const u32 has_data = TIS_STS_DATA_AVAILABLE | TIS_STS_VALID; 418 | u32 expected_count = *len; 419 | int max_cycles = 0; 420 | 421 | /* Wait for the TPM to process the command. */ 422 | value = tis_wait_reg(&lpc_tpm_dev[locality].tpm_status, 423 | has_data, has_data); 424 | if (value == TPM_TIMEOUT_ERR) { 425 | printf("%s:%d failed processing command\n", 426 | __FILE__, __LINE__); 427 | return TPM_DRIVER_ERR; 428 | } 429 | 430 | do { 431 | while ((burst = burst_count(value)) == 0) { 432 | if (max_cycles++ == MAX_DELAY_US) { 433 | printf("%s:%d TPM stuck on read\n", 434 | __FILE__, __LINE__); 435 | return TPM_DRIVER_ERR; 436 | } 437 | udelay(1); 438 | value = tpm_read_word(&lpc_tpm_dev 439 | [locality].tpm_status); 440 | } 441 | 442 | max_cycles = 0; 443 | 444 | while (burst-- && (offset < expected_count)) { 445 | buffer[offset++] = tpm_read_byte(&lpc_tpm_dev 446 | [locality].data); 447 | 448 | if (offset == 6) { 449 | /* 450 | * We got the first six bytes of the reply, 451 | * let's figure out how many bytes to expect 452 | * total - it is stored as a 4 byte number in 453 | * network order, starting with offset 2 into 454 | * the body of the reply. 455 | */ 456 | u32 real_length; 457 | memcpy(&real_length, 458 | buffer + 2, 459 | sizeof(real_length)); 460 | expected_count = be32_to_cpu(real_length); 461 | 462 | if ((expected_count < offset) || 463 | (expected_count > *len)) { 464 | printf("%s:%d bad response size %d\n", 465 | __FILE__, __LINE__, 466 | expected_count); 467 | return TPM_DRIVER_ERR; 468 | } 469 | } 470 | } 471 | 472 | /* Wait for the next portion. */ 473 | value = tis_wait_reg(&lpc_tpm_dev[locality].tpm_status, 474 | TIS_STS_VALID, TIS_STS_VALID); 475 | if (value == TPM_TIMEOUT_ERR) { 476 | printf("%s:%d failed to read response\n", 477 | __FILE__, __LINE__); 478 | return TPM_DRIVER_ERR; 479 | } 480 | 481 | if (offset == expected_count) 482 | break; /* We got all we needed. */ 483 | 484 | } while ((value & has_data) == has_data); 485 | 486 | /* 487 | * Make sure we indeed read all there was. The TIS_STS_VALID bit is 488 | * known to be set. 489 | */ 490 | if (value & TIS_STS_DATA_AVAILABLE) { 491 | printf("%s:%d wrong receive status %x\n", 492 | __FILE__, __LINE__, value); 493 | return TPM_DRIVER_ERR; 494 | } 495 | 496 | /* Tell the TPM that we are done. */ 497 | if (tis_command_ready(locality) == TPM_TIMEOUT_ERR) 498 | return TPM_DRIVER_ERR; 499 | 500 | *len = offset; 501 | return 0; 502 | } 503 | 504 | int tis_open(void) 505 | { 506 | u8 locality = 0; /* we use locality zero for everything. */ 507 | 508 | if (tis_close()) 509 | return TPM_DRIVER_ERR; 510 | 511 | /* now request access to locality. */ 512 | tpm_write_word(TIS_ACCESS_REQUEST_USE, &lpc_tpm_dev[locality].access); 513 | 514 | /* did we get a lock? */ 515 | if (tis_wait_reg(&lpc_tpm_dev[locality].access, 516 | TIS_ACCESS_ACTIVE_LOCALITY, 517 | TIS_ACCESS_ACTIVE_LOCALITY) == TPM_TIMEOUT_ERR) { 518 | printf("%s:%d - failed to lock locality %d\n", 519 | __FILE__, __LINE__, locality); 520 | return TPM_DRIVER_ERR; 521 | } 522 | 523 | /* Certain TPMs need some delay here or they hang. */ 524 | udelay(10); 525 | 526 | if (tis_command_ready(locality) == TPM_TIMEOUT_ERR) 527 | return TPM_DRIVER_ERR; 528 | 529 | return 0; 530 | } 531 | 532 | int tis_close(void) 533 | { 534 | u8 locality = 0; 535 | 536 | if (tpm_read_word(&lpc_tpm_dev[locality].access) & 537 | TIS_ACCESS_ACTIVE_LOCALITY) { 538 | tpm_write_word(TIS_ACCESS_ACTIVE_LOCALITY, 539 | &lpc_tpm_dev[locality].access); 540 | 541 | if (tis_wait_reg(&lpc_tpm_dev[locality].access, 542 | TIS_ACCESS_ACTIVE_LOCALITY, 0) == 543 | TPM_TIMEOUT_ERR) { 544 | printf("%s:%d - failed to release locality %d\n", 545 | __FILE__, __LINE__, locality); 546 | return TPM_DRIVER_ERR; 547 | } 548 | } 549 | return 0; 550 | } 551 | 552 | int tis_sendrecv(const u8 *sendbuf, size_t send_size, 553 | u8 *recvbuf, size_t *recv_len) 554 | { 555 | if (tis_senddata(sendbuf, send_size)) { 556 | printf("%s:%d failed sending data to TPM\n", 557 | __FILE__, __LINE__); 558 | return TPM_DRIVER_ERR; 559 | } 560 | 561 | return tis_readresponse(recvbuf, (u32 *)recv_len); 562 | } 563 | -------------------------------------------------------------------------------- /include/sboot.h: -------------------------------------------------------------------------------- 1 | /* Secure Boot implemented with a Static Root of Trust Measurement (SRTM). 2 | * The Static Root is assuming to be implemented in SPL (Second Phase Loader), 3 | * thus we can implement a trusted or secure boot with relying on chip or board 4 | * manufactures. The implementor must ensure the SPL executes from Read-Only NV storage. 5 | * 6 | * BeagleBone implementation of SRTM using SPL: 7 | * Public ROM (operating in public-CPU mode) boots from a hard-order: mmc0, spi0, uart0, usb0. 8 | * By loading SPL on MMC0, and pulling the WP pin on MMC0 high we prevent modification to the SPL. 9 | * (This can also be implemented using spi0, or uart0, without attaching an MMC0.) 10 | * U-Boot, boot configuration data (i.e., uEnv.txt), kernel, and disk are located on MMC1. 11 | * 12 | * TPM Operations (Baseline Trusted Boot Components): 13 | * SPL: sboot_init() -> initialize TPM, run SelfTest, enable physical presence 14 | * SPL: sboot_read_uboot() -> PCR Extend for "firmware" 15 | * SPL: sboot_read_eeprom() -> PCR Extend for EEPROM data 16 | * UBT: sboot_read_bootoptions() -> PCR Extend for boot configuration data, may include additional EEPROM data 17 | * UBT: sboot_read_kernel() -> PCR Extend for Linux kernel 18 | * UBT: sboot_seal() -> Save PCR context using Skey^i to untrusted store 19 | * - verify key can be used for secure storage 20 | * - create context using key and PCR values (uboot, config, kernel) 21 | * - generate symmetric encryption key (FSkey) for filesystem 22 | * - encrypt, store, and return FSkey 23 | * - optionally encrypt FS on MMC1 24 | * 25 | * TPM Operations (Booting Securely): 26 | * SPL: sboot_init() -> initialize TPM, run SelfTest, enable physical presence 27 | * SPL: sboot_read_uboot() -> PCR Extend for boot loader 28 | * - read u-boot binary from mmc1 29 | * - calculate SHA1, extend SBOOT_PCR_UBOOT 30 | * SPL: sboot_read_eeprom() -> PCR Extend for EEPROM data 31 | * - read EEPROM (various methods) 32 | * - calculate SHA1, extend SBOOT_PCR_UBOOT 33 | * UBT: sboot_read_bootoptions() -> PCR Extend for boot configuration data 34 | * - read uEnv.txt from mmc1 35 | * - calculate SHA1, extend SBOOT_PCR_UBOOT 36 | * UBT: sboot_read_kernel() -> PCR Extend for Linux kernel 37 | * - read uImage from mmc1 38 | * - calculate SHA1, extend SBOOT_PCR_KERNEL 39 | * KRN: sboot_unseal() -> [or UBT] Decrypt filesystem symmetric encryption key. 40 | * - use SKey^i and PCRs to unseal protected storage 41 | * KRN: sboot_lock_pcrs() -> extend all used PCRs with random data 42 | * KRN: sboot_finish() -> optionally remove physical presence 43 | * 44 | */ 45 | #ifndef SBOOT_H_ 46 | #define SBOOT_H_ 47 | 48 | #include 49 | #include 50 | 51 | #include 52 | 53 | /* TSS-defined (section here) PCR locations for UBOOT and OS Kernel */ 54 | /* Todo: this should be represented as a linked list, this will ease iteration 55 | * and allow developers to easily add data for measurement (other than static 56 | * defines of PCR values). 57 | */ 58 | #define SBOOT_PCR_UBOOT 0x1 59 | #define SBOOT_PCR_CHIPSET_CONFIG 0x2 60 | #define SBOOT_PCR_UBOOT_ENVIRONMENT 0x3 61 | #define SBOOT_PCR_UBOOT_CONSOLE 0x4 62 | #define SBOOT_PCR_UBOOT_MEMORY 0x4 63 | #define SBOOT_PCR_KERNEL 0x5 64 | 65 | #define SBOOT_SPL_READ_SIZE (0x1 << 15) /* 32K */ 66 | 67 | /* Temporary (simple) SBOOT errors */ 68 | #define SBOOT_SUCCESS 0x0 69 | #define SBOOT_TPM_ERROR 0x1 70 | #define SBOOT_DATA_ERROR 0x2 71 | 72 | #define SBOOT_SEAL_WELL_KNOWN_KEY 0x10 73 | #define SBOOT_NV_INDEX_SEAL_OS 0xd000 74 | #define SBOOT_NV_INDEX_SEAL_UBOOT 0xe000 75 | 76 | /* SPL functions */ 77 | /* Extend PCRs for U-boot and EEPROM */ 78 | void spl_sboot_extend(void); 79 | /* Load sealed data and verify */ 80 | void spl_sboot_check(void); 81 | 82 | /* U-Boot functions */ 83 | __attribute__((unused)) 84 | uint8_t sboot_extend_console(const char *buffer, uint32_t size); 85 | __attribute__((unused)) 86 | uint8_t sboot_extend_environment(const char *buffer, uint32_t size); 87 | 88 | /* Seal toggle will set an environment variable that bootm checks. 89 | * If this variable is still set when bootm is executed, it will 90 | * run sboot_seal_os(void); which is a simple wrapper for sboot_seal 91 | * with a well-known key value and configured nv_index as SBOOT_NV_INDEX_SEAL_OS. 92 | */ 93 | __attribute__((unused)) 94 | uint8_t sboot_seal_toggle(void); 95 | __attribute__((unused)) 96 | uint8_t sboot_seal_os(void); 97 | __attribute__((unused)) 98 | uint8_t sboot_seal_uboot(void); 99 | uint8_t sboot_seal(const uint8_t *key, uint32_t keySize, 100 | uint32_t pcrMap, uint16_t nv_index); 101 | uint8_t sboot_unseal(const uint8_t *sealData, uint32_t sealDataSize, 102 | uint8_t *unsealData, uint32_t *unsealDataSize); 103 | 104 | /* Initialization steps needed for TPM: 105 | * TlclStartup() 106 | * TlclSelfTestFull() //optional 107 | */ 108 | __attribute__((unused)) 109 | uint8_t sboot_init(void); 110 | 111 | __attribute__((unused)) 112 | uint8_t sboot_check_os(void); 113 | uint8_t sboot_check(uint16_t nv_index); 114 | 115 | /* Performs a TlclExtend (TPM PCR Extend) with the given 20 byte hash */ 116 | uint8_t sboot_extend(uint16_t pcr, const uint8_t* in_digest, uint8_t* out_digest); 117 | 118 | uint8_t sboot_read_uboot(const uint8_t* in_digest); 119 | uint8_t sboot_read_kernel(const uint8_t* in_digest); 120 | uint8_t sboot_read_bootoptions(const uint8_t* in_digest); 121 | 122 | /* After system is booted, lock PCRS by extending with random data. */ 123 | __attribute__((unused)) 124 | uint8_t sboot_lock_pcrs(void); 125 | __attribute__((unused)) 126 | uint8_t sboot_finish(void); 127 | 128 | #endif /* SBOOT_H_ */ 129 | -------------------------------------------------------------------------------- /include/tlcl.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 The Chromium OS Authors. All rights reserved. 2 | * Use of this source code is governed by a BSD-style license that can be 3 | * found in the LICENSE file. 4 | */ 5 | 6 | /* TPM Lightweight Command Library. 7 | * 8 | * A low-level library for interfacing to TPM hardware or an emulator. 9 | */ 10 | 11 | #ifndef TPM_LITE_TLCL_H_ 12 | #define TPM_LITE_TLCL_H_ 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | 19 | /*****************************************************************************/ 20 | /* Functions implemented in tlcl.c */ 21 | 22 | /* Needed for oiaposap */ 23 | uint32_t TlclSendReceive(const uint8_t* request, uint8_t* response, int max_length); 24 | uint32_t Send(const uint8_t* command); 25 | 26 | /* Call this first. Returns 0 if success, nonzero if error. 27 | */ 28 | __attribute__((unused)) 29 | uint32_t TlclLibInit(void); 30 | 31 | /* Call this on shutdown. Returns 0 if success, nonzero if error. 32 | */ 33 | uint32_t TlclLibClose(void); 34 | 35 | /* Logs to stdout. Arguments like printf. 36 | */ 37 | void TlclLog(char* format, ...); 38 | 39 | /* Sets the log level. 0 is quietest. 40 | */ 41 | void TlclSetLogLevel(int level); 42 | 43 | /* Sends a TPM_Startup(ST_CLEAR). The TPM error code is returned (0 44 | * for success). 45 | */ 46 | uint32_t TlclStartup(void); 47 | 48 | /* Save the TPM state. Normally done by the kernel before a suspend, included 49 | * here for tests. The TPM error code is returned (0 for success). 50 | */ 51 | uint32_t TlclSaveState(void); 52 | 53 | /* Resumes by sending a TPM_Startup(ST_STATE). The TPM error code is returned 54 | * (0 for success). 55 | */ 56 | uint32_t TlclResume(void); 57 | 58 | /* Runs the self test. Note---this is synchronous. To run this in parallel 59 | * with other firmware, use ContinueSelfTest. The TPM error code is returned. 60 | */ 61 | uint32_t TlclSelfTestFull(void); 62 | 63 | /* Runs the self test in the background. 64 | */ 65 | uint32_t TlclContinueSelfTest(void); 66 | 67 | /* Defines a space with permission [perm]. [index] is the index for the space, 68 | * [size] the usable data size. The TPM error code is returned. 69 | */ 70 | uint32_t TlclDefineSpace(uint32_t index, uint32_t perm, uint32_t size); 71 | 72 | /* Writes [length] bytes of [data] to space at [index]. The TPM error code is 73 | * returned. 74 | */ 75 | uint32_t TlclWrite(uint32_t index, const void* data, uint32_t length); 76 | 77 | /* Reads [length] bytes from space at [index] into [data]. The TPM error code 78 | * is returned. 79 | */ 80 | uint32_t TlclRead(uint32_t index, void* data, uint32_t length); 81 | 82 | /* Reads PCR at [index] into [data]. [length] must be TPM_PCR_DIGEST or 83 | * larger. The TPM error code is returned. 84 | */ 85 | uint32_t TlclPCRRead(uint32_t index, void* data, uint32_t length); 86 | 87 | /* Write-locks space at [index]. The TPM error code is returned. 88 | */ 89 | uint32_t TlclWriteLock(uint32_t index); 90 | 91 | /* Read-locks space at [index]. The TPM error code is returned. 92 | */ 93 | uint32_t TlclReadLock(uint32_t index); 94 | 95 | /* Asserts physical presence in software. The TPM error code is returned. 96 | */ 97 | uint32_t TlclAssertPhysicalPresence(void); 98 | 99 | /* Enables the physical presence command. The TPM error code is returned. 100 | */ 101 | uint32_t TlclPhysicalPresenceCMDEnable(void); 102 | 103 | /* Finalizes the physical presence settings: sofware PP is enabled, hardware PP 104 | * is disabled, and the lifetime lock is set. The TPM error code is returned. 105 | */ 106 | uint32_t TlclFinalizePhysicalPresence(void); 107 | 108 | /* Turns off physical presence and locks it off until next reboot. The TPM 109 | * error code is returned. 110 | */ 111 | uint32_t TlclLockPhysicalPresence(void); 112 | 113 | /* Sets the nvLocked bit. The TPM error code is returned. 114 | */ 115 | uint32_t TlclSetNvLocked(void); 116 | 117 | /* Returns 1 if the TPM is owned, 0 otherwise. 118 | */ 119 | int TlclIsOwned(void); 120 | 121 | /* Issues a ForceClear. The TPM error code is returned. 122 | */ 123 | uint32_t TlclForceClear(void); 124 | 125 | /* Issues a PhysicalEnable. The TPM error code is returned. 126 | */ 127 | uint32_t TlclSetEnable(void); 128 | 129 | /* Issues a PhysicalDisable. The TPM error code is returned. 130 | */ 131 | uint32_t TlclClearEnable(void); 132 | 133 | /* Issues a SetDeactivated. Pass 0 to activate. Returns result code. 134 | */ 135 | uint32_t TlclSetDeactivated(uint8_t flag); 136 | 137 | /* Gets flags of interest. Pointers for flags you aren't interested in may 138 | * be NULL. The TPM error code is returned. 139 | */ 140 | uint32_t TlclGetFlags(uint8_t* disable, uint8_t* deactivated, 141 | uint8_t* nvlocked); 142 | 143 | /* Sets the bGlobalLock flag, which only a reboot can clear. The TPM error 144 | * code is returned. 145 | */ 146 | uint32_t TlclSetGlobalLock(void); 147 | 148 | /* Performs a TPM_Extend. 149 | */ 150 | uint32_t TlclExtend(int pcr_num, const uint8_t* in_digest, uint8_t* out_digest); 151 | 152 | /* Gets the permission bits for the NVRAM space with |index|. 153 | */ 154 | uint32_t TlclGetPermissions(uint32_t index, uint32_t* permissions); 155 | 156 | /* Gets the entire set of permanent flags. 157 | */ 158 | uint32_t TlclGetPermanentFlags(TPM_PERMANENT_FLAGS* pflags); 159 | 160 | /* Gets the entire set of volatile (ST_CLEAR) flags. 161 | */ 162 | uint32_t TlclGetSTClearFlags(TPM_STCLEAR_FLAGS* pflags); 163 | 164 | /* Gets ownership flag. The TPM error code is returned. 165 | */ 166 | uint32_t TlclGetOwnership(uint8_t* owned); 167 | 168 | /* Requests [length] bytes from TPM RNG to be stored in [data]. Actual 169 | * number of bytes read is stored in [size]. The TPM error code is returned. 170 | */ 171 | uint32_t TlclGetRandom(uint8_t* data, uint32_t length, uint32_t* size); 172 | 173 | /* Resets the TPM, removing loaded keys and opened handles. 174 | */ 175 | uint32_t TlclReset(void); 176 | 177 | /* Seal commands */ 178 | uint32_t TlclSeal(uint32_t keyHandle, const uint8_t *pcrInfo, uint32_t pcrInfoSize, const uint8_t *keyAuth, const uint8_t *dataAuth, const uint8_t *data, uint32_t dataSize, uint8_t *blob, uint32_t *blobSize); 179 | uint32_t TSS_GenPCRInfo(uint32_t pcrMap, uint8_t *pcrInfo, uint32_t *size); 180 | uint32_t TlclSealPCR(uint32_t keyHandle, uint32_t pcrMap, const uint8_t *keyAuth, const uint8_t *dataAuth, const uint8_t *data, uint32_t dataSize, uint8_t *blob, uint32_t *blobSize); 181 | uint32_t TlclUnseal(uint32_t keyHandle, const uint8_t *keyAuth, const uint8_t *dataAuth, const uint8_t *blob, uint32_t blobSize, uint8_t *rawData, uint32_t *dataSize); 182 | 183 | /* Key structures */ 184 | typedef struct Tlcl_PublicKeyData { 185 | uint32_t algorithm; 186 | uint16_t encscheme; 187 | uint16_t sigscheme; 188 | uint32_t keybitlen; 189 | uint32_t numprimes; 190 | uint32_t expsize; 191 | uint8_t exponent[3]; 192 | uint32_t keylength; 193 | uint8_t modulus[256]; 194 | uint32_t pcrinfolen; 195 | uint8_t pcrinfo[256]; 196 | } Tlcl_PublicKeyData; 197 | 198 | typedef struct Tlcl_KeyData { 199 | uint8_t version[4]; 200 | uint16_t keyusage; 201 | uint32_t keyflags; 202 | uint8_t authdatausage; 203 | Tlcl_PublicKeyData pub; 204 | uint32_t privkeylen; 205 | uint8_t encprivkey[1024]; 206 | } Tlcl_KeyData; 207 | 208 | uint32_t TlclGetCapability(uint32_t capability, 209 | uint8_t *subCap, uint32_t subCapSize, 210 | uint8_t *response, uint32_t *responseSize); 211 | uint32_t TlclCreateWrapKey(uint32_t parentKeyHandle, uint8_t *parentKeyAuth, 212 | uint8_t *keyAuth, uint8_t *migrationAuth, 213 | Tlcl_KeyData *keyParams, Tlcl_KeyData *key, 214 | uint8_t *keyBlob, uint32_t *blobSize); 215 | 216 | #endif /* TPM_LITE_TLCL_H_ */ 217 | -------------------------------------------------------------------------------- /include/tss_constants.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 The Chromium OS Authors. All rights reserved. 2 | * Use of this source code is governed by a BSD-style license that can be 3 | * found in the LICENSE file. 4 | * 5 | * Some TPM constants and type definitions for standalone compilation for use in 6 | * the firmware 7 | */ 8 | 9 | #ifndef VBOOT_REFERENCE_TSS_CONSTANTS_H_ 10 | #define VBOOT_REFERENCE_TSS_CONSTANTS_H_ 11 | 12 | #include 13 | 14 | #define TPM_MAX_COMMAND_SIZE 1024 15 | #define TPM_LARGE_ENOUGH_COMMAND_SIZE 256 /* saves space in the firmware */ 16 | #define TPM_PUBEK_SIZE 256 17 | #define TPM_PCR_DIGEST 20 18 | #define TPM_DATA_OFFSET 10 19 | 20 | #define TPM_E_NON_FATAL 0x800 21 | 22 | #define TPM_SUCCESS ((uint32_t)0x00000000) 23 | 24 | #define TPM_E_AREA_LOCKED ((uint32_t)0x0000003c) 25 | #define TPM_E_BADINDEX ((uint32_t)0x00000002) 26 | #define TPM_E_BAD_PRESENCE ((uint32_t)0x0000002d) 27 | #define TPM_E_IOERROR ((uint32_t)0x0000001f) 28 | #define TPM_E_INVALID_POSTINIT ((uint32_t)0x00000026) 29 | #define TPM_E_MAXNVWRITES ((uint32_t)0x00000048) 30 | #define TPM_E_OWNER_SET ((uint32_t)0x00000014) 31 | 32 | #define TPM_E_NEEDS_SELFTEST ((uint32_t)(TPM_E_NON_FATAL + 1)) 33 | #define TPM_E_DOING_SELFTEST ((uint32_t)(TPM_E_NON_FATAL + 2)) 34 | 35 | #define TPM_E_ALREADY_INITIALIZED ((uint32_t)0x00005000) /* vboot local */ 36 | #define TPM_E_INTERNAL_INCONSISTENCY ((uint32_t)0x00005001) /* vboot local */ 37 | #define TPM_E_MUST_REBOOT ((uint32_t)0x00005002) /* vboot local */ 38 | #define TPM_E_CORRUPTED_STATE ((uint32_t)0x00005003) /* vboot local */ 39 | #define TPM_E_COMMUNICATION_ERROR ((uint32_t)0x00005004) /* vboot local */ 40 | #define TPM_E_RESPONSE_TOO_LARGE ((uint32_t)0x00005005) /* vboot local */ 41 | #define TPM_E_NO_DEVICE ((uint32_t)0x00005006) /* vboot local */ 42 | #define TPM_E_INPUT_TOO_SMALL ((uint32_t)0x00005007) /* vboot local */ 43 | #define TPM_E_WRITE_FAILURE ((uint32_t)0x00005008) /* vboot local */ 44 | #define TPM_E_READ_EMPTY ((uint32_t)0x00005009) /* vboot local */ 45 | #define TPM_E_READ_FAILURE ((uint32_t)0x0000500a) /* vboot local */ 46 | 47 | #define TPM_E_NULL_ARG ((uint32_t)0x80001002) /* An argument was NULL */ 48 | #define TPM_E_BAD_ARG ((uint32_t)0x80001003) /* An argument had an invalid value */ 49 | #define TPM_E_HMAC_FAIL ((uint32_t)0x80001004) /* HMAC validation failed */ 50 | 51 | #define TPM_NV_INDEX0 ((uint32_t)0x00000000) 52 | #define TPM_NV_INDEX_LOCK ((uint32_t)0xffffffff) 53 | #define TPM_NV_PER_GLOBALLOCK (((uint32_t)1)<<15) 54 | #define TPM_NV_PER_PPWRITE (((uint32_t)1)<<0) 55 | #define TPM_NV_PER_PPREAD (((uint32_t)1)<<16) 56 | #define TPM_NV_PER_READ_STCLEAR (((uint32_t)1)<<31) 57 | #define TPM_NV_PER_WRITE_STCLEAR (((uint32_t)1)<<14) 58 | 59 | #define TPM_TAG_RQU_COMMAND ((uint16_t) 0xc1) 60 | #define TPM_TAG_RQU_AUTH1_COMMAND ((uint16_t) 0xc2) 61 | #define TPM_TAG_RQU_AUTH2_COMMAND ((uint16_t) 0xc3) 62 | 63 | #define TPM_TAG_RSP_COMMAND ((uint16_t) 0xc4) 64 | #define TPM_TAG_RSP_AUTH1_COMMAND ((uint16_t) 0xc5) 65 | #define TPM_TAG_RSP_AUTH2_COMMAND ((uint16_t) 0xc6) 66 | 67 | typedef uint8_t TSS_BOOL; 68 | typedef uint16_t TPM_STRUCTURE_TAG; 69 | 70 | typedef struct tdTPM_PERMANENT_FLAGS 71 | { 72 | TPM_STRUCTURE_TAG tag; 73 | TSS_BOOL disable; 74 | TSS_BOOL ownership; 75 | TSS_BOOL deactivated; 76 | TSS_BOOL readPubek; 77 | TSS_BOOL disableOwnerClear; 78 | TSS_BOOL allowMaintenance; 79 | TSS_BOOL physicalPresenceLifetimeLock; 80 | TSS_BOOL physicalPresenceHWEnable; 81 | TSS_BOOL physicalPresenceCMDEnable; 82 | TSS_BOOL CEKPUsed; 83 | TSS_BOOL TPMpost; 84 | TSS_BOOL TPMpostLock; 85 | TSS_BOOL FIPS; 86 | TSS_BOOL Operator; 87 | TSS_BOOL enableRevokeEK; 88 | TSS_BOOL nvLocked; 89 | TSS_BOOL readSRKPub; 90 | TSS_BOOL tpmEstablished; 91 | TSS_BOOL maintenanceDone; 92 | TSS_BOOL disableFullDALogicInfo; 93 | } TPM_PERMANENT_FLAGS; 94 | 95 | typedef struct tdTPM_STCLEAR_FLAGS{ 96 | TPM_STRUCTURE_TAG tag; 97 | TSS_BOOL deactivated; 98 | TSS_BOOL disableForceClear; 99 | TSS_BOOL physicalPresence; 100 | TSS_BOOL physicalPresenceLock; 101 | TSS_BOOL bGlobalLock; 102 | } TPM_STCLEAR_FLAGS; 103 | 104 | #endif /* VBOOT_REFERENCE_TSS_CONSTANTS_H_ */ 105 | -------------------------------------------------------------------------------- /lib/sboot/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2012 Teddy Reed 2 | 3 | include $(TOPDIR)/config.mk 4 | 5 | LIB = $(obj)libsboot.o 6 | 7 | SOBJS = 8 | 9 | CFLAGS += -I$(VBOOT_SOURCE)/firmware/include -I$(VBOOT_SOURCE)/firmware/arch/$(ARCH)/include 10 | 11 | ifdef CONFIG_SPL_BUILD 12 | COBJS-$(CONFIG_SPL_SBOOT_SUPPORT) += spl_sboot.o 13 | endif 14 | 15 | COBJS-$(CONFIG_SBOOT) += sboot.o 16 | 17 | COBJS = $(COBJS-y) 18 | SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) 19 | OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) 20 | 21 | $(LIB): $(obj).depend $(OBJS) 22 | $(call cmd_link_o_target, $(OBJS)) 23 | 24 | ######################################################################### 25 | 26 | # defines $(obj).depend target 27 | include $(SRCTREE)/rules.mk 28 | 29 | sinclude $(obj).depend 30 | 31 | ######################################################################### 32 | -------------------------------------------------------------------------------- /lib/sboot/sboot.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libsboot - U-Boot Trusted/Secured Boot implementation. 3 | * Author: Teddy Reed 4 | * 5 | * Sboot depends on libtlcl, a lite TSS based on tlcl from the Chromium Project's vboot. 6 | * The functions defined in libsboot are implemented in U-boot and optionally in SPL. 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | #define TPM_BASE 0 15 | #define TPM_INVALID_POSTINIT (TPM_BASE+38) 16 | 17 | /* May turn off physical presence, may allow for a trusted boot instead of secure. */ 18 | __attribute__((unused)) 19 | uint8_t sboot_finish(void); 20 | 21 | #ifndef CONFIG_SBOOT_DISABLE_CONSOLE_EXTEND 22 | /* If SBOOT is extending console commands then it has two options for 23 | * measurement, as it must consider measuring the act of sealing measurement: 24 | * 1. Check for the SBOOT seal command, and skip measurement. 25 | * 2. Always measure the SBOOT seal command before booting. 26 | * Finally, to preserve automatic booting, the default boot command (and legacy variants) 27 | * should not be measured. 28 | */ 29 | const char *console_measure_exceptions[] = { 30 | "sboot seal", "boot", "bootd" 31 | }; 32 | #endif 33 | 34 | /* TPM must be started, enabled, activated, and owned. 35 | * If not owned, OSAP will return a key use error. 36 | */ 37 | __attribute__((unused)) 38 | uint8_t sboot_seal(const uint8_t *key, uint32_t keySize, 39 | uint32_t pcrMap, uint16_t nv_index) 40 | { 41 | uint32_t result; 42 | 43 | uint32_t keyHandle; 44 | uint8_t keyAuth[20]; 45 | uint8_t dataAuth[20]; 46 | 47 | uint8_t blob[312]; 48 | uint32_t blobSize; 49 | 50 | /* Max size of key */ 51 | if (keySize > 96) { 52 | return SBOOT_DATA_ERROR; 53 | } 54 | 55 | /* Use SRK for encrypting */ 56 | keyHandle = 0x40000000; 57 | 58 | /* default TPM passwords */ 59 | memset(keyAuth, 0, 20); 60 | memset(dataAuth, 0, 20); 61 | 62 | TlclLibInit(); 63 | 64 | result = TlclSealPCR(keyHandle, pcrMap, keyAuth, dataAuth, 65 | key, keySize, blob, &blobSize); 66 | 67 | if (result != TPM_SUCCESS) { 68 | /* problem */ 69 | debug("sboot: Failed to seal.\n"); 70 | return SBOOT_TPM_ERROR; 71 | } 72 | 73 | debug("sboot: Writing blob to NVRAM: (index=%d).\n", nv_index); 74 | 75 | result = TlclWrite(nv_index, (void *) blob, blobSize); 76 | debug("sboot: write complete.\n"); 77 | if (result != TPM_SUCCESS) { 78 | debug("sboot: Failed to write NVRAM.\n"); 79 | return SBOOT_TPM_ERROR; 80 | } 81 | 82 | debug("sboot: Seal success.\n"); 83 | return 0; 84 | } 85 | 86 | __attribute__((unused)) 87 | uint8_t sboot_seal_toggle(void) 88 | { 89 | int result; 90 | 91 | result = setenv("sbootseal", "bootm"); 92 | if (result != 0) 93 | return SBOOT_DATA_ERROR; 94 | return SBOOT_SUCCESS; 95 | } 96 | 97 | __attribute__((unused)) 98 | uint8_t sboot_seal_uboot(void) 99 | { 100 | uint8_t result; 101 | 102 | uint32_t pcrMap; 103 | uint8_t key[20]; 104 | 105 | /* Create bitmap of PCR registers to seal on */ 106 | pcrMap = 0 + (1 << SBOOT_PCR_UBOOT) + (1 << SBOOT_PCR_CHIPSET_CONFIG); 107 | 108 | memset(key, SBOOT_SEAL_WELL_KNOWN_KEY, 20); 109 | result = sboot_seal(key, 20, pcrMap, SBOOT_NV_INDEX_SEAL_UBOOT); 110 | 111 | return result; 112 | } 113 | 114 | __attribute__((unused)) 115 | uint8_t sboot_seal_os(void) 116 | { 117 | uint8_t result; 118 | 119 | uint32_t pcrMap; 120 | uint8_t key[20]; 121 | 122 | /* Create bitmap of PCR registers to seal on */ 123 | pcrMap = 0 + (1 << SBOOT_PCR_UBOOT) + (1 << SBOOT_PCR_CHIPSET_CONFIG) + 124 | (1 << SBOOT_PCR_KERNEL); 125 | /* Only add PCRs if measuring environment and console. */ 126 | #ifndef CONFIG_SBOOT_UBOOT_DISABLE_ENV_EXTEND 127 | pcrMap += (1 << SBOOT_PCR_UBOOT_ENVIRONMENT); 128 | #endif 129 | #ifndef CONFIG_SBOOT_UBOOT_DISABLE_CONSOLE_EXTEND 130 | pcrMap += (1 << SBOOT_PCR_UBOOT_CONSOLE); 131 | #endif 132 | 133 | memset(key, SBOOT_SEAL_WELL_KNOWN_KEY, 20); 134 | result = sboot_seal(key, 20, pcrMap, SBOOT_NV_INDEX_SEAL_OS); 135 | 136 | return result; 137 | } 138 | 139 | uint8_t sboot_unseal(const uint8_t *sealData, uint32_t sealDataSize, 140 | uint8_t *unsealData, uint32_t *unsealDataSize) 141 | { 142 | uint32_t result; 143 | 144 | uint8_t keyAuth[20]; 145 | uint8_t dataAuth[20]; 146 | 147 | /* Use WK-password for SRK and data */ 148 | memset(keyAuth, 0, 20); 149 | memset(dataAuth, 0, 20); 150 | result = TlclUnseal(0x40000000, keyAuth, dataAuth, 151 | sealData, sealDataSize, unsealData, unsealDataSize); 152 | if (result != TPM_SUCCESS) { 153 | debug("sboot: Failed to unseal data.\n"); 154 | return SBOOT_DATA_ERROR; 155 | } 156 | 157 | return SBOOT_SUCCESS; 158 | } 159 | 160 | uint8_t sboot_init(void) 161 | { 162 | uint32_t tpm_result; 163 | 164 | TSS_BOOL disabled, deactivated, nvlocked; 165 | uint8_t pcrCheck[20], pcrDefault[20]; 166 | uint32_t permissions; 167 | 168 | puts("Sboot initializing SRTM\n"); 169 | 170 | TlclLibInit(); 171 | 172 | tpm_result = TlclStartup(); 173 | if (tpm_result != TPM_SUCCESS && tpm_result != TPM_INVALID_POSTINIT) { 174 | /* Invalid Postinit is returned if TPM is already started */ 175 | goto error; 176 | } 177 | 178 | TlclSelfTestFull(); /* Required by some TPMs */ 179 | TlclSetNvLocked(); /* Enforce security controls on NVRAM. */ 180 | TlclGetFlags(&disabled, &deactivated, &nvlocked); 181 | 182 | if (disabled == 1 || deactivated == 1) { 183 | /* TPM is deactivated or disabled, possibly try to enable/activate */ 184 | /* Todo: SBOOT should return an error notifying the implementor to 185 | * configure (enable/activate) their TPM 186 | */ 187 | /* Todo: Set enabled and activated, then try again. */ 188 | debug("sboot: The TPM is disabled or deactivated.\n"); 189 | goto error; 190 | } 191 | 192 | if (nvlocked != 1) { 193 | /* TPM's NVRAM is not locked, meaning there is no read/write control 194 | * enforcement. SBOOT can set GlobalLock, but the Owner should also 195 | * be set (which should happen external to SBOOT). If the Owner is set 196 | * then the defined NVRAM indexes need to be defined with PPREAD|PPWRITE. 197 | */ 198 | debug("sboot: The TPM NVRAM is not locked.\n"); 199 | goto error; 200 | } 201 | 202 | /* Check PCR values, they should be 0, else they will need to be reset. 203 | * A reset can occur via operator authentication or a physical reset. 204 | */ 205 | memset(pcrDefault, 0x0, 20); 206 | tpm_result = TlclPCRRead(SBOOT_PCR_UBOOT, (void *) pcrCheck, 20); 207 | if (tpm_result != TPM_SUCCESS || memcmp(pcrCheck, pcrDefault, 20) != 0) { 208 | debug("sboot: UBOOT PCR is unreadable or extended.\n"); 209 | tpm_result = SBOOT_TPM_ERROR; 210 | goto error; 211 | } 212 | tpm_result = TlclPCRRead(SBOOT_PCR_CHIPSET_CONFIG, (void *) pcrCheck, 20); 213 | if (tpm_result != TPM_SUCCESS || memcmp(pcrCheck, pcrDefault, 20) != 0) { 214 | debug("sboot: CHIPSET CONFIG PCR is unreadable or extended.\n"); 215 | tpm_result = SBOOT_TPM_ERROR; 216 | goto error; 217 | } 218 | tpm_result = TlclPCRRead(SBOOT_PCR_UBOOT_ENVIRONMENT, (void *) pcrCheck, 20); 219 | if (tpm_result != TPM_SUCCESS || memcmp(pcrCheck, pcrDefault, 20) != 0) { 220 | debug("sboot: UBOOT ENVIRONMENT PCR is unreadable or extended.\n"); 221 | tpm_result = SBOOT_TPM_ERROR; 222 | goto error; 223 | } 224 | tpm_result = TlclPCRRead(SBOOT_PCR_UBOOT_CONSOLE, (void *) pcrCheck, 20); 225 | if (tpm_result != TPM_SUCCESS || memcmp(pcrCheck, pcrDefault, 20) != 0) { 226 | debug("sboot: UBOOT CONSOLE PCR is unreadable or extended.\n"); 227 | tpm_result = SBOOT_TPM_ERROR; 228 | goto error; 229 | } 230 | tpm_result = TlclPCRRead(SBOOT_PCR_KERNEL, (void *) pcrCheck, 20); 231 | if (tpm_result != TPM_SUCCESS || memcmp(pcrCheck, pcrDefault, 20) != 0) { 232 | debug("sboot: KERNEL PCR is unreadable or extended.\n"); 233 | tpm_result = SBOOT_TPM_ERROR; 234 | goto error; 235 | } 236 | 237 | 238 | /* Check NVRAM indexes and permissions, the permissions must be PPREAD|PPWRITE */ 239 | tpm_result = TlclGetPermissions(SBOOT_NV_INDEX_SEAL_UBOOT, &permissions); 240 | if (tpm_result != TPM_SUCCESS) { 241 | debug("sboot: failed to get permissions for NVRAM UBOOT_SEAL (index=%d).\n", SBOOT_NV_INDEX_SEAL_UBOOT); 242 | goto error; 243 | } 244 | if (permissions != (TPM_NV_PER_PPWRITE|TPM_NV_PER_PPREAD)) { 245 | debug("sboot: NVRAM permissions for UBOOT_SEAL are incorrect (perm=%d).\n", permissions); 246 | goto error; 247 | } 248 | 249 | TlclGetPermissions(SBOOT_NV_INDEX_SEAL_OS, &permissions); 250 | if (tpm_result != TPM_SUCCESS) { 251 | debug("sboot: Failed to get permissions for NVRAM OS_SEAL (index=%d).\n", SBOOT_NV_INDEX_SEAL_OS); 252 | goto error; 253 | } 254 | if (permissions != (TPM_NV_PER_PPWRITE|TPM_NV_PER_PPREAD)) { 255 | debug("sboot: NVRAM permissions for OS_SEAL are incorrect (perm=%d).\n", permissions); 256 | goto error; 257 | } 258 | 259 | /* Physical presence must match the security controls on NVRAM. */ 260 | tpm_result = TlclAssertPhysicalPresence(); 261 | if (tpm_result != TPM_SUCCESS) { 262 | debug("sboot: Failed to enable Physical Presence\n"); 263 | } 264 | 265 | error: 266 | if (tpm_result != TPM_SUCCESS) { 267 | puts("sboot: Failed to initialize TPM\n"); 268 | return SBOOT_TPM_ERROR; 269 | } 270 | 271 | return SBOOT_SUCCESS; 272 | } 273 | 274 | /* Read seal data containing 312 bytes (20byte encrypted hash) from TPM NVRAM. 275 | * Try to unseal (verifying correct PCR values). 276 | * 277 | * If CONFIG_SBOOT_ENFORCE is enabled sboot_check will hang on failure. 278 | */ 279 | uint8_t sboot_check(uint16_t nv_index) 280 | { 281 | uint32_t result; 282 | 283 | uint32_t unsealDataSize; 284 | uint8_t sealData[312]; 285 | uint8_t unsealData[20]; 286 | 287 | result = TlclRead(nv_index, sealData, 312); 288 | if (result != TPM_SUCCESS) { 289 | debug("sboot: failed to read seal data from %d.\n", nv_index); 290 | return SBOOT_TPM_ERROR; 291 | } 292 | 293 | /* no need to check unsealed data */ 294 | result = sboot_unseal(sealData, 312, unsealData, &unsealDataSize); 295 | if (result != SBOOT_SUCCESS) { 296 | debug("sboot: failed to unseal.\n"); 297 | return SBOOT_DATA_ERROR; 298 | } 299 | 300 | #ifdef CONFIG_SBOOT_ENFORCE 301 | puts("\n\n(Critical!) System state change detected\n"); 302 | sboot_finish(); 303 | hang(); 304 | #endif 305 | 306 | return SBOOT_SUCCESS; 307 | } 308 | 309 | __attribute__((unused)) 310 | uint8_t sboot_check_os(void) 311 | { 312 | return sboot_check(SBOOT_NV_INDEX_SEAL_OS); 313 | } 314 | 315 | __attribute__((unused)) 316 | uint8_t sboot_extend(uint16_t pcr, const uint8_t* in_digest, uint8_t* out_digest) 317 | { 318 | TlclLibInit(); 319 | 320 | if (TlclExtend(pcr, in_digest, out_digest) != TPM_SUCCESS) 321 | return SBOOT_TPM_ERROR; 322 | 323 | return SBOOT_SUCCESS; 324 | } 325 | 326 | #ifndef CONFIG_SBOOT_DISABLE_CONSOLE_EXTEND 327 | __attribute__((unused)) 328 | uint8_t sboot_extend_console(const char *buffer, uint32_t max_size) 329 | { 330 | uint32_t size; 331 | uint8_t i = 0; 332 | 333 | uint8_t digest[20], out_digest[20]; 334 | SHA1_CTX ctx; 335 | 336 | /* sboot will extend the console up to the max_size given to the command. 337 | * It is possible that input validation did not happen on buffer, thus 338 | * max_size is an explicit parameter to the memory compare. 339 | * 340 | * max_size is not used by default, as it is possible the memory 341 | * space after the null-terminated buffer was NOT scrubbed. 342 | */ 343 | size = (strlen(buffer) < max_size) ? strlen(buffer) : max_size; 344 | 345 | /* Do not seal if command buffer is a measurement exception */ 346 | for (i = 0; i < sizeof(console_measure_exceptions) / sizeof(char *); ++i) { 347 | if (strlen(console_measure_exceptions[i]) == size && 348 | memcmp(console_measure_exceptions[i], console_buffer, size) == 0) { 349 | return SBOOT_DATA_ERROR; 350 | } 351 | } 352 | 353 | debug("sboot: Extending console with \"%s\" (size=%d).\n", buffer, size); 354 | 355 | sha1_starts(&ctx); /* could be 1 function, sha1_csum */ 356 | sha1_update(&ctx, (const unsigned char*) buffer, size); 357 | sha1_finish(&ctx, digest); 358 | 359 | return sboot_extend(SBOOT_PCR_UBOOT_CONSOLE, digest, out_digest); 360 | } 361 | #endif 362 | 363 | #ifndef CONFIG_SBOOT_DISABLE_ENV_EXTEND 364 | __attribute__((unused)) 365 | uint8_t sboot_extend_environment(const char *buffer, uint32_t size) 366 | { 367 | uint8_t digest[20], out_digest[20]; 368 | SHA1_CTX ctx; 369 | 370 | debug("sboot: Extending env with \"%s\" (size=%d).\n", buffer, size); 371 | 372 | sha1_starts(&ctx); /* could be 1 function, sha1_csum */ 373 | sha1_update(&ctx, (const unsigned char*) buffer, size); 374 | sha1_finish(&ctx, digest); 375 | 376 | return sboot_extend(SBOOT_PCR_UBOOT_ENVIRONMENT, digest, out_digest); 377 | } 378 | #endif 379 | 380 | __attribute__((unused)) 381 | uint8_t sboot_extend_os(const uint8_t* start, uint32_t size) 382 | { 383 | /* uint32_t i; */ 384 | uint8_t digest[20], out_digest[20]; 385 | SHA1_CTX ctx; 386 | 387 | if (size == 0) 388 | return SBOOT_SUCCESS; 389 | 390 | debug("sboot: Extending OS (addr=%x, size=%d)\n", (uint32_t) start, size); 391 | 392 | sha1_starts(&ctx); 393 | sha1_update(&ctx, start, size); 394 | sha1_finish(&ctx, digest); 395 | 396 | return sboot_extend(SBOOT_PCR_KERNEL, digest, out_digest); 397 | } 398 | 399 | __attribute__((unused)) 400 | uint8_t sboot_lock_pcrs(void) 401 | { 402 | uint8_t lockNonce[20]; /* should be TPM_NONCE_SIZE */ 403 | uint32_t size; 404 | uint8_t output[20]; 405 | 406 | TlclGetRandom(lockNonce, 20, &size); 407 | 408 | sboot_extend(SBOOT_PCR_UBOOT, lockNonce, output); 409 | sboot_extend(SBOOT_PCR_CHIPSET_CONFIG, lockNonce, output); 410 | sboot_extend(SBOOT_PCR_UBOOT_ENVIRONMENT, lockNonce, output); 411 | sboot_extend(SBOOT_PCR_UBOOT_CONSOLE, lockNonce, output); 412 | sboot_extend(SBOOT_PCR_UBOOT_MEMORY, lockNonce, output); 413 | sboot_extend(SBOOT_PCR_KERNEL, lockNonce, output); 414 | return SBOOT_SUCCESS; 415 | } 416 | 417 | __attribute__((unused)) 418 | uint8_t sboot_finish(void) 419 | { 420 | /* Remove PP, thus locking READ/WRITE to NVRAM. */ 421 | debug("sboot: finished; locking PCRs and Physical Presence.\n"); 422 | sboot_lock_pcrs(); 423 | TlclLockPhysicalPresence(); 424 | 425 | return SBOOT_SUCCESS; 426 | } 427 | -------------------------------------------------------------------------------- /lib/sboot/spl_sboot.c: -------------------------------------------------------------------------------- 1 | /* 2 | * spl_sboot.c 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | /* spl_image defined in spl.c */ 14 | void spl_sboot_extend(void) 15 | { 16 | uint8_t csum[20]; 17 | uint8_t out_digest[20]; 18 | 19 | uint8_t image_buffer[SBOOT_SPL_READ_SIZE]; 20 | uint32_t i; 21 | SHA1_CTX ctx; 22 | 23 | sha1_starts(&ctx); 24 | /* Only support MMC/FAT */ 25 | #if defined(CONFIG_SPL_MMC_SUPPORT) && defined(CONFIG_SPL_FAT_SUPPORT) 26 | /* Todo: add a configuration option to limit the memory read length. 27 | * This will allow us to SHA1 in blocks. 28 | * Todo: add a configuration option to use the TPM's SHA1 for extreme 29 | * memory contention scenarios. */ 30 | sha1_update(&ctx, (unsigned char *) spl_image.load_addr, spl_image.size); 31 | #else 32 | #warning "Warning: sboot does not support the U-Boot storage configuration." 33 | #endif 34 | sha1_finish(&ctx, csum); 35 | 36 | if (sboot_extend(SBOOT_PCR_UBOOT, csum, out_digest) != SBOOT_SUCCESS) { 37 | puts("SPL: (sboot) error while measuring U-Boot\n"); 38 | return; 39 | } 40 | 41 | sha1_starts(&ctx); 42 | /* Extend EEPROM, support I2C only */ 43 | #ifdef CONFIG_ENV_EEPROM_IS_ON_I2C 44 | /* 45 | for (i = 0; i * SBOOT_SPL_READ_SIZE < CONFIG_SYS_I2C_EEPROM_SIZE; ++i) { 46 | memset(image_buffer, 0, SBOOT_SPL_READ_SIZE); 47 | if (i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, 0, CONFIG_SYS_I2C_EEPROM_ADDR_LEN, 48 | image_buffer, SBOOT_SPL_READ_SIZE)) { 49 | puts("SPL: (sboot) could not read the EEPROM\n"); 50 | return; 51 | } 52 | sha1_update(&ctx, image_buffer, SBOOT_SPL_READ_SIZE); 53 | }*/ 54 | debug("SPL: (sboot) measuring EEPROM\n"); 55 | i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, 0, CONFIG_SYS_I2C_EEPROM_ADDR_LEN, image_buffer, CONFIG_SYS_I2C_EEPROM_SIZE); 56 | sha1_update(&ctx, image_buffer, CONFIG_SYS_I2C_EEPROM_SIZE); 57 | debug("SPL: (sboot) finished\n"); 58 | #else 59 | #warning "Warning: sboot does not support the ENV storage configuration." 60 | #endif 61 | sha1_finish(&ctx, csum); 62 | 63 | if (sboot_extend(SBOOT_PCR_CHIPSET_CONFIG, csum, out_digest) != SBOOT_SUCCESS) { 64 | puts("SPL: (sboot) error while measuring chipset config\n"); 65 | return; 66 | } 67 | } 68 | 69 | void spl_sboot_check(void) 70 | { 71 | #ifndef CONFIG_SBOOT_UBOOT_SEAL_INDEX 72 | puts("SPL: (sboot) no U-boot seal index defined\n"); 73 | hang(); 74 | #endif 75 | 76 | puts("SPL: (Sboot) measuring U-Boot ... "); 77 | if (sboot_check(SBOOT_NV_INDEX_SEAL_UBOOT) != SBOOT_SUCCESS) { 78 | /* If CONFIG_SBOOT_ENFORCE is enabled the system is already hung. */ 79 | puts("Failed\n"); 80 | return; 81 | } 82 | 83 | puts("OK\n"); 84 | } 85 | -------------------------------------------------------------------------------- /lib/tlcl/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2012 Teddy Reed 2 | 3 | include $(TOPDIR)/config.mk 4 | 5 | LIB = $(obj)libtlcl.o 6 | 7 | SOBJS = 8 | 9 | COBJS-$(CONFIG_TPM) += oiaposap.o tlcl.o 10 | COBJS-$(CONFIG_TLCL_SEAL) += tlcl_seal.o tlcl_hmac.o 11 | COBJS-$(CONFIG_TLCL_KEYS) += tlcl_keys.o tlcl_hmac.o 12 | 13 | COBJS = $(COBJS-y) 14 | SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) 15 | OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) 16 | 17 | $(LIB): $(obj).depend $(OBJS) 18 | $(call cmd_link_o_target, $(OBJS)) 19 | 20 | ######################################################################### 21 | 22 | # defines $(obj).depend target 23 | include $(SRCTREE)/rules.mk 24 | 25 | sinclude $(obj).depend 26 | 27 | ######################################################################### 28 | -------------------------------------------------------------------------------- /lib/tlcl/oiaposap.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libtpm: OAIP/OSAP routines 3 | * Copyright (C) 2004 IBM Corporation 4 | * Author: J. Kravitz 5 | * 6 | * tlcl implementation 7 | * Copyright (C) 2012 V Lab Technologies 8 | * Author: Teddy Reed 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | */ 15 | 16 | #include 17 | #include 18 | 19 | #include "oiaposap.h" 20 | #include "oiaposap_structures.h" 21 | 22 | /**************************************************************************** 23 | * 24 | * Open an OIAP session 25 | * Object Independent Authorization Protocol, will not work on commands 26 | * that introduce new AuthData to the TPM 27 | * 28 | ****************************************************************************/ 29 | uint32_t TSS_OIAPopen(uint32_t *handle, uint8_t *enonce) 30 | { 31 | struct s_tpm_oiap_open_cmd cmd; 32 | uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; 33 | uint32_t result; 34 | 35 | debug("TPM: TSS_OIAPopen\n"); 36 | /* check input arguments */ 37 | if (handle == NULL || enonce == NULL) { 38 | return TPM_E_NULL_ARG; 39 | } 40 | 41 | memcpy(&cmd, &tpm_oiap_open_cmd, sizeof(cmd)); 42 | result = TlclSendReceive(cmd.buffer, response, sizeof(response)); 43 | 44 | if (result == TPM_SUCCESS) { 45 | FromTpmUint32(response + kTpmResponseHeaderLength, handle); 46 | memcpy(enonce, response + kTpmResponseHeaderLength + sizeof(uint32_t), TPM_NONCE_SIZE); 47 | } 48 | 49 | return result; 50 | } 51 | 52 | /****************************************************************************/ 53 | /* */ 54 | /* Close an OIAP session */ 55 | /* */ 56 | /****************************************************************************/ 57 | uint32_t TSS_OIAPclose(uint32_t handle) 58 | { 59 | return TSS_HANDclose(handle); 60 | } 61 | 62 | /**************************************************************************** 63 | * 64 | * Open an OSAP session 65 | * Object Specific Authorization Protocol, returned handle must manipulate 66 | * a single object given as a parameter (can introduce AuthData). 67 | * * 68 | ****************************************************************************/ 69 | uint32_t TSS_OSAPopen(struct tss_osapsess *sess, const uint8_t *key, uint16_t etype, 70 | uint32_t evalue) 71 | { 72 | struct s_tpm_osap_open_cmd cmd; 73 | uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; 74 | uint32_t nonceSize; 75 | uint32_t result; 76 | 77 | debug("TPM: TSS_OSAPopen\n"); 78 | /* check input arguments */ 79 | if (key == NULL || sess == NULL) { 80 | return TPM_E_NULL_ARG; 81 | } 82 | 83 | TlclGetRandom(sess->ononceOSAP, TPM_NONCE_SIZE, &nonceSize); 84 | 85 | memcpy(&cmd, &tpm_osap_open_cmd, sizeof(cmd)); 86 | ToTpmUint16(cmd.buffer + tpm_osap_open_cmd.type, etype); 87 | ToTpmUint32(cmd.buffer + tpm_osap_open_cmd.value, evalue); 88 | memcpy(cmd.buffer + tpm_osap_open_cmd.nonce, sess->ononceOSAP, TPM_NONCE_SIZE); 89 | 90 | result = TlclSendReceive(cmd.buffer, response, sizeof(response)); 91 | 92 | if (result == TPM_SUCCESS) { 93 | FromTpmUint32(response + kTpmResponseHeaderLength, &(sess->handle)); 94 | memcpy(sess->enonce, response + kTpmResponseHeaderLength + sizeof(uint32_t), TPM_NONCE_SIZE); 95 | memcpy(sess->enonceOSAP, response + kTpmResponseHeaderLength + sizeof(uint32_t) + TPM_NONCE_SIZE, TPM_NONCE_SIZE); 96 | 97 | debug("TPM: TSS_OSAPopen success, calculating HMAC\n"); 98 | /*DATA_DEBUG("key", key, TPM_HASH_SIZE); 99 | DATA_DEBUG("enonceOSAP", sess->enonceOSAP, TPM_NONCE_SIZE); 100 | DATA_DEBUG("ononceOSAP", sess->ononceOSAP, TPM_NONCE_SIZE);*/ 101 | 102 | /* not implemented */ 103 | SHA1_CTX hmac; 104 | hmac_starts(&hmac, key, TPM_HASH_SIZE); 105 | hmac_update(&hmac, sess->enonceOSAP, TPM_NONCE_SIZE); 106 | hmac_update(&hmac, sess->ononceOSAP, TPM_NONCE_SIZE); 107 | hmac_finish(&hmac, key, TPM_HASH_SIZE, sess->ssecret); 108 | } 109 | 110 | return result; 111 | } 112 | 113 | /****************************************************************************/ 114 | /* */ 115 | /* Close an OSAP session */ 116 | /* */ 117 | /****************************************************************************/ 118 | uint32_t TSS_OSAPclose(struct tss_osapsess *sess) 119 | { 120 | uint32_t ret; 121 | 122 | if (sess == NULL) 123 | return TPM_E_NULL_ARG; 124 | ret = TSS_HANDclose(sess->handle); 125 | return ret; 126 | } 127 | 128 | /****************************************************************************/ 129 | /* */ 130 | /* Terminate the Handle Opened by TPM_OIAPOpen, or TPM_OSAPOpen */ 131 | /* */ 132 | /****************************************************************************/ 133 | uint32_t TSS_HANDclose(uint32_t handle) 134 | { 135 | struct s_tpm_handle_close_cmd cmd; 136 | uint32_t result; 137 | 138 | memcpy(&cmd, &tpm_handle_close_cmd, sizeof(cmd)); 139 | ToTpmUint32(cmd.buffer + tpm_handle_close_cmd.handle, handle); 140 | 141 | result = Send(cmd.buffer); 142 | return result; 143 | } 144 | -------------------------------------------------------------------------------- /lib/tlcl/oiaposap.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libtpm: oiaposap.h 3 | * 4 | * Copyright (C) 2004 IBM Corporation 5 | * Author: J. Kravitz 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | */ 12 | 13 | #ifndef OIAPOSAP_H 14 | #define OIAPOSAP_H 15 | #include "tlcl_internal.h" 16 | 17 | struct tss_osapsess { 18 | uint32_t handle; 19 | uint8_t enonce[TPM_NONCE_SIZE]; 20 | uint8_t enonceOSAP[TPM_NONCE_SIZE]; 21 | uint8_t ononceOSAP[TPM_NONCE_SIZE]; 22 | uint8_t ssecret[TPM_HASH_SIZE]; 23 | uint8_t ononce[TPM_NONCE_SIZE]; 24 | }; 25 | 26 | uint32_t TSS_HANDclose(uint32_t handle); 27 | uint32_t TSS_OIAPopen(uint32_t * handle, uint8_t *enonce); 28 | uint32_t TSS_OIAPclose(uint32_t handle); 29 | uint32_t TSS_OSAPopen(struct tss_osapsess *sess, 30 | const uint8_t *key, uint16_t etype, uint32_t evalue); 31 | uint32_t TSS_OSAPclose(struct tss_osapsess *sess); 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /lib/tlcl/oiaposap_structures.h: -------------------------------------------------------------------------------- 1 | /* 2 | * tlcl OIAP/OSAP structures 3 | * Copyright (C) 2012 V Lab Technologies 4 | * Author: Teddy Reed 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | */ 11 | 12 | #ifndef OIAPOSAP_STRUCTURES_H_ 13 | #define OIAPOSAP_STRUCTURES_H_ 14 | 15 | const struct s_tpm_oiap_open_cmd { 16 | uint8_t buffer[10]; 17 | } tpm_oiap_open_cmd = {{ 18 | 0x0, 0xc1, 19 | 0x0, 0x0, 0x0, 0xa, 20 | 0x0, 0x0, 0x0, 0xa 21 | }, }; 22 | 23 | const struct s_tpm_osap_open_cmd { 24 | uint8_t buffer[64]; 25 | uint8_t type; 26 | uint8_t value; 27 | uint8_t nonce; 28 | } tpm_osap_open_cmd = {{ 29 | 0x0, 0xc1, 30 | 0x0, 0x0, 0x0, 0x24, /* 2 + 4 + 4 + 2 + 4 + 20 */ 31 | 0x0, 0x0, 0x0, 0x0B, 32 | }, 10, 12, 16}; 33 | 34 | const struct s_tpm_handle_close_cmd { 35 | uint8_t buffer[14]; 36 | uint16_t handle; 37 | } tpm_handle_close_cmd = {{ 38 | 0x0, 0xc1, 39 | 0x0, 0x0, 0x0, 0xe, 40 | 0x0, 0x0, 0x0, 0x96, 41 | }, 10, }; 42 | 43 | 44 | #endif /* OIAPOSAP_STRUCTURES_H_ */ 45 | -------------------------------------------------------------------------------- /lib/tlcl/tlcl.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 The Chromium OS Authors. All rights reserved. 2 | * Use of this source code is governed by a BSD-style license that can be 3 | * found in the LICENSE file. 4 | */ 5 | 6 | /* A lightweight TPM command library. 7 | * 8 | * The general idea is that TPM commands are array of bytes whose 9 | * fields are mostly compile-time constant. The goal is to build much 10 | * of the commands at compile time (or build time) and change some of 11 | * the fields at run time as needed. The code in 12 | * utility/tlcl_generator.c builds structures containing the commands, 13 | * as well as the offsets of the fields that need to be set at run 14 | * time. 15 | */ 16 | 17 | #include 18 | 19 | #include "tlcl_internal.h" 20 | #include "tlcl_structures.h" 21 | 22 | #ifdef CONFIG_TLCL_DEBUG 23 | static void inline DATA_DEBUG(const char *label, const uint8_t *data, uint32_t size) { 24 | uint16_t i; 25 | 26 | debug("[TPM] %s", label); 27 | for (i=0; i 10) 83 | DATA_DEBUG("\t", request+10, TpmCommandSize(request)-10); 84 | #endif 85 | 86 | result = tis_sendrecv(request, TpmCommandSize(request), response, &response_length); 87 | if (0 != result) { 88 | /* Communication with TPM failed, so response is garbage */ 89 | debug("TPM: command 0x%x send/receive failed: 0x%x\n", TpmCommandCode(request), result); 90 | return result; 91 | } 92 | 93 | /* Otherwise, use the result code from the response */ 94 | result = TpmReturnCode(response); 95 | 96 | /* TODO: add paranoia about returned response_length vs. max_length 97 | * (and possibly expected length from the response header). See 98 | * crosbug.com/17017 */ 99 | 100 | #ifdef CONFIG_TLCL_DEBUG 101 | debug("TPM: response: %x %x, %x %x %x %x, %x %x %x %x (size=%d)\n", 102 | response[0], response[1], 103 | response[2], response[3], response[4], response[5], 104 | response[6], response[7], response[8], response[9], TpmCommandSize(response)); 105 | if (TpmCommandSize(response) > 10) 106 | DATA_DEBUG("\t", response+10, TpmCommandSize(response)-10); 107 | #endif 108 | 109 | debug("TPM: command 0x%x returned 0x%x\n", TpmCommandCode(request), result); 110 | 111 | return result; 112 | } 113 | 114 | 115 | /* Sends a TPM command and gets a response. Returns 0 if success or the TPM 116 | * error code if error. In the firmware, waits for the self test to complete 117 | * if needed. In the host, reports the first error without retries. */ 118 | uint32_t TlclSendReceive(const uint8_t* request, uint8_t* response, 119 | int max_length) 120 | { 121 | uint32_t result = TlclSendReceiveNoRetry(request, response, max_length); 122 | 123 | /* If the command fails because the self test has not completed, try it 124 | * again after attempting to ensure that the self test has completed. */ 125 | if (result == TPM_E_NEEDS_SELFTEST || result == TPM_E_DOING_SELFTEST) { 126 | result = TlclContinueSelfTest(); 127 | if (result != TPM_SUCCESS) { 128 | return result; 129 | } 130 | 131 | /* This needs serious testing. The TPM specification says: "iii. The 132 | * caller MUST wait for the actions of TPM_ContinueSelfTest to complete 133 | * before reissuing the command C1." But, if ContinueSelfTest is 134 | * non-blocking, how do we know that the actions have completed other than 135 | * trying again? */ 136 | do { 137 | result = TlclSendReceiveNoRetry(request, response, max_length); 138 | } while (result == TPM_E_DOING_SELFTEST); 139 | 140 | } 141 | return result; 142 | } 143 | 144 | /* Sends a command and returns the error code. */ 145 | uint32_t Send(const uint8_t* command) 146 | { 147 | uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; 148 | 149 | return TlclSendReceive(command, response, sizeof(response)); 150 | } 151 | 152 | /* Exported functions. */ 153 | __attribute__((unused)) 154 | uint32_t TlclLibInit(void) 155 | { 156 | if (tis_init()) { 157 | return -1; 158 | } 159 | 160 | return tis_open(); 161 | } 162 | 163 | uint32_t TlclLibClose(void) 164 | { 165 | return tis_close(); 166 | } 167 | 168 | uint32_t TlclStartup(void) 169 | { 170 | debug("TPM: Startup\n"); 171 | TlclLibInit(); 172 | return Send(tpm_startup_cmd.buffer); 173 | } 174 | 175 | uint32_t TlclSaveState(void) 176 | { 177 | debug("TPM: SaveState\n"); 178 | return Send(tpm_savestate_cmd.buffer); 179 | } 180 | 181 | uint32_t TlclResume(void) 182 | { 183 | debug("TPM: Resume\n"); 184 | return Send(tpm_resume_cmd.buffer); 185 | } 186 | 187 | uint32_t TlclSelfTestFull(void) 188 | { 189 | debug("TPM: Self test full\n"); 190 | return Send(tpm_selftestfull_cmd.buffer); 191 | } 192 | 193 | uint32_t TlclContinueSelfTest(void) 194 | { 195 | uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; 196 | 197 | debug("TPM: Continue self test\n"); 198 | /* Call the No Retry version of SendReceive to avoid recursion. */ 199 | return TlclSendReceiveNoRetry(tpm_continueselftest_cmd.buffer, 200 | response, sizeof(response)); 201 | } 202 | 203 | uint32_t TlclDefineSpace(uint32_t index, uint32_t perm, uint32_t size) 204 | { 205 | struct s_tpm_nv_definespace_cmd cmd; 206 | 207 | debug("TPM: TlclDefineSpace(0x%x, 0x%x, %d)\n", index, perm, size); 208 | memcpy(&cmd, &tpm_nv_definespace_cmd, sizeof(cmd)); 209 | ToTpmUint32(cmd.buffer + tpm_nv_definespace_cmd.index, index); 210 | ToTpmUint32(cmd.buffer + tpm_nv_definespace_cmd.perm, perm); 211 | ToTpmUint32(cmd.buffer + tpm_nv_definespace_cmd.size, size); 212 | 213 | return Send(cmd.buffer); 214 | } 215 | 216 | uint32_t TlclWrite(uint32_t index, const void* data, uint32_t length) 217 | { 218 | struct s_tpm_nv_write_cmd cmd; 219 | const int total_length = 220 | kTpmRequestHeaderLength + kWriteInfoLength + length; 221 | 222 | debug("TPM: TlclWrite(0x%x, %d)\n", index, length); 223 | memcpy(&cmd, &tpm_nv_write_cmd, sizeof(cmd)); 224 | assert(total_length <= TPM_MAX_COMMAND_SIZE); 225 | SetTpmCommandSize(cmd.buffer, total_length); 226 | 227 | ToTpmUint32(cmd.buffer + tpm_nv_write_cmd.index, index); 228 | ToTpmUint32(cmd.buffer + tpm_nv_write_cmd.length, length); 229 | memcpy(cmd.buffer + tpm_nv_write_cmd.data, data, length); 230 | 231 | return Send(cmd.buffer); 232 | } 233 | 234 | uint32_t TlclRead(uint32_t index, void* data, uint32_t length) 235 | { 236 | struct s_tpm_nv_read_cmd cmd; 237 | uint8_t response[TPM_MAX_COMMAND_SIZE]; 238 | uint32_t result_length; 239 | uint32_t result; 240 | 241 | debug("TPM: TlclRead(0x%x, %d)\n", index, length); 242 | memcpy(&cmd, &tpm_nv_read_cmd, sizeof(cmd)); 243 | ToTpmUint32(cmd.buffer + tpm_nv_read_cmd.index, index); 244 | ToTpmUint32(cmd.buffer + tpm_nv_read_cmd.length, length); 245 | 246 | result = TlclSendReceive(cmd.buffer, response, sizeof(response)); 247 | if (result == TPM_SUCCESS && length > 0) { 248 | uint8_t* nv_read_cursor = response + kTpmResponseHeaderLength; 249 | FromTpmUint32(nv_read_cursor, &result_length); 250 | nv_read_cursor += sizeof(uint32_t); 251 | memcpy(data, nv_read_cursor, result_length); 252 | } 253 | 254 | return result; 255 | } 256 | 257 | /* read PCR[index] into data of length */ 258 | uint32_t TlclPCRRead(uint32_t index, void* data, uint32_t length) 259 | { 260 | struct s_tpm_nv_read_cmd cmd; 261 | uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; 262 | uint32_t result; 263 | 264 | debug("TPM: TlclPCRRead(0x%x, %d)\n", index, length); 265 | if (length < kPcrDigestLength) { 266 | return TPM_E_IOERROR; 267 | } 268 | memcpy(&cmd, &tpm_pcr_read_cmd, sizeof(cmd)); 269 | ToTpmUint32(cmd.buffer + tpm_pcr_read_cmd.pcrNum, index); 270 | 271 | result = TlclSendReceive(cmd.buffer, response, sizeof(response)); 272 | if (result == TPM_SUCCESS) { 273 | uint8_t* pcr_read_cursor = response + kTpmResponseHeaderLength; 274 | memcpy(data, pcr_read_cursor, kPcrDigestLength); 275 | } 276 | 277 | return result; 278 | } 279 | 280 | uint32_t TlclWriteLock(uint32_t index) 281 | { 282 | debug("TPM: Write lock 0x%x\n", index); 283 | return TlclWrite(index, NULL, 0); 284 | } 285 | 286 | uint32_t TlclReadLock(uint32_t index) 287 | { 288 | debug("TPM: Read lock 0x%x\n", index); 289 | return TlclRead(index, NULL, 0); 290 | } 291 | 292 | uint32_t TlclAssertPhysicalPresence(void) 293 | { 294 | debug("TPM: Asserting physical presence\n"); 295 | return Send(tpm_ppassert_cmd.buffer); 296 | } 297 | 298 | uint32_t TlclPhysicalPresenceCMDEnable(void) 299 | { 300 | debug("TPM: Enable the physical presence command\n"); 301 | return Send(tpm_ppenable_cmd.buffer); 302 | } 303 | 304 | uint32_t TlclFinalizePhysicalPresence(void) 305 | { 306 | debug("TPM: Enable PP cmd, disable HW pp, and set lifetime lock\n"); 307 | return Send(tpm_finalizepp_cmd.buffer); 308 | } 309 | 310 | uint32_t TlclAssertPhysicalPresenceResult(void) 311 | { 312 | debug("TPM: Asserting physical presence\n"); 313 | uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; 314 | return TlclSendReceive(tpm_ppassert_cmd.buffer, response, sizeof(response)); 315 | } 316 | 317 | uint32_t TlclLockPhysicalPresence(void) 318 | { 319 | debug("TPM: Lock physical presence\n"); 320 | return Send(tpm_pplock_cmd.buffer); 321 | } 322 | 323 | uint32_t TlclSetNvLocked(void) 324 | { 325 | debug("TPM: Set NV locked\n"); 326 | return TlclDefineSpace(TPM_NV_INDEX_LOCK, 0, 0); 327 | } 328 | 329 | uint32_t TlclReset(void) 330 | { 331 | debug("TPM: Reset\n"); 332 | return Send(tpm_reset_cmd.buffer); 333 | } 334 | 335 | int TlclIsOwned(void) 336 | { 337 | uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE + TPM_PUBEK_SIZE]; 338 | uint32_t result; 339 | result = TlclSendReceive(tpm_readpubek_cmd.buffer, 340 | response, sizeof(response)); 341 | return (result != TPM_SUCCESS); 342 | } 343 | 344 | uint32_t TlclForceClear(void) 345 | { 346 | debug("TPM: Force clear\n"); 347 | return Send(tpm_forceclear_cmd.buffer); 348 | } 349 | 350 | uint32_t TlclSetEnable(void) 351 | { 352 | debug("TPM: Enabling TPM\n"); 353 | return Send(tpm_physicalenable_cmd.buffer); 354 | } 355 | 356 | uint32_t TlclClearEnable(void) 357 | { 358 | debug("TPM: Disabling TPM\n"); 359 | return Send(tpm_physicaldisable_cmd.buffer); 360 | } 361 | 362 | uint32_t TlclSetDeactivated(uint8_t flag) 363 | { 364 | struct s_tpm_physicalsetdeactivated_cmd cmd; 365 | 366 | debug("TPM: SetDeactivated(%d)\n", flag); 367 | memcpy(&cmd, &tpm_physicalsetdeactivated_cmd, sizeof(cmd)); 368 | *(cmd.buffer + cmd.deactivated) = flag; 369 | return Send(cmd.buffer); 370 | } 371 | 372 | uint32_t TlclGetPermanentFlags(TPM_PERMANENT_FLAGS* pflags) 373 | { 374 | uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; 375 | uint32_t size; 376 | uint32_t result; 377 | 378 | result = TlclSendReceive(tpm_getflags_cmd.buffer, response, sizeof(response)); 379 | if (result != TPM_SUCCESS) 380 | return result; 381 | 382 | FromTpmUint32(response + kTpmResponseHeaderLength, &size); 383 | 384 | /* Edge-case, chip supports less than len(FLAGS). */ 385 | memset(pflags, 0, sizeof(TPM_PERMANENT_FLAGS)); 386 | memcpy(pflags, 387 | response + kTpmResponseHeaderLength + sizeof(size), 388 | size); 389 | 390 | return result; 391 | } 392 | 393 | uint32_t TlclGetSTClearFlags(TPM_STCLEAR_FLAGS* vflags) 394 | { 395 | uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; 396 | uint32_t size; 397 | uint32_t result; 398 | 399 | result = TlclSendReceive(tpm_getstclearflags_cmd.buffer, response, sizeof(response)); 400 | if (result != TPM_SUCCESS) 401 | return result; 402 | 403 | FromTpmUint32(response + kTpmResponseHeaderLength, &size); 404 | /* Ugly assertion, but the struct is padded up by one byte. */ 405 | assert(size == 7 && sizeof(TPM_STCLEAR_FLAGS) - 1 == 7); 406 | memcpy(vflags, 407 | response + kTpmResponseHeaderLength + sizeof(size), 408 | sizeof(TPM_STCLEAR_FLAGS)); 409 | return result; 410 | } 411 | 412 | uint32_t TlclGetFlags(uint8_t* disable, uint8_t* deactivated, uint8_t *nvlocked) 413 | { 414 | TPM_PERMANENT_FLAGS pflags; 415 | uint32_t result; 416 | 417 | result = TlclGetPermanentFlags(&pflags); 418 | if (result == TPM_SUCCESS) { 419 | if (disable) 420 | *disable = pflags.disable; 421 | if (deactivated) 422 | *deactivated = pflags.deactivated; 423 | if (nvlocked) 424 | *nvlocked = pflags.nvLocked; 425 | debug("TPM: Got flags disable=%d, deactivated=%d, nvlocked=%d\n", 426 | pflags.disable, pflags.deactivated, pflags.nvLocked); 427 | } 428 | 429 | return result; 430 | } 431 | 432 | uint32_t TlclSetGlobalLock(void) 433 | { 434 | uint32_t x; 435 | 436 | debug("TPM: Set global lock\n"); 437 | return TlclWrite(TPM_NV_INDEX0, (uint8_t*) &x, 0); 438 | } 439 | 440 | uint32_t TlclExtend(int pcr_num, const uint8_t* in_digest, uint8_t* out_digest) 441 | { 442 | struct s_tpm_extend_cmd cmd; 443 | uint8_t response[kTpmResponseHeaderLength + kPcrDigestLength]; 444 | uint32_t result; 445 | 446 | memcpy(&cmd, &tpm_extend_cmd, sizeof(cmd)); 447 | ToTpmUint32(cmd.buffer + tpm_extend_cmd.pcrNum, pcr_num); 448 | memcpy(cmd.buffer + cmd.inDigest, in_digest, kPcrDigestLength); 449 | 450 | result = TlclSendReceive(cmd.buffer, response, sizeof(response)); 451 | if (result != TPM_SUCCESS) 452 | return result; 453 | 454 | memcpy(out_digest, response + kTpmResponseHeaderLength, kPcrDigestLength); 455 | 456 | return result; 457 | } 458 | 459 | uint32_t TlclGetPermissions(uint32_t index, uint32_t* permissions) 460 | { 461 | struct s_tpm_getpermissions_cmd cmd; 462 | uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; 463 | uint8_t* nvdata; 464 | uint32_t result; 465 | uint32_t size; 466 | 467 | memcpy(&cmd, &tpm_getpermissions_cmd, sizeof(cmd)); 468 | ToTpmUint32(cmd.buffer + tpm_getpermissions_cmd.index, index); 469 | result = TlclSendReceive(cmd.buffer, response, sizeof(response)); 470 | if (result != TPM_SUCCESS) 471 | return result; 472 | 473 | nvdata = response + kTpmResponseHeaderLength + sizeof(size); 474 | FromTpmUint32(nvdata + kNvDataPublicPermissionsOffset, permissions); 475 | 476 | return result; 477 | } 478 | 479 | uint32_t TlclGetOwnership(uint8_t* owned) { 480 | uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; 481 | uint32_t size; 482 | uint32_t result; 483 | 484 | result = TlclSendReceive(tpm_getownership_cmd.buffer, response, sizeof(response)); 485 | if (result != TPM_SUCCESS) 486 | return result; 487 | 488 | FromTpmUint32(response + kTpmResponseHeaderLength, &size); 489 | assert(size == sizeof(*owned)); 490 | memcpy(owned, 491 | response + kTpmResponseHeaderLength + sizeof(size), 492 | sizeof(*owned)); 493 | 494 | return result; 495 | } 496 | 497 | /* request 'length' random bytes to 'data', 'size' will return length of bytes */ 498 | uint32_t TlclGetRandom(uint8_t* data, uint32_t length, uint32_t *size) 499 | { 500 | struct s_tpm_get_random_cmd cmd; 501 | uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; 502 | uint32_t result; 503 | 504 | debug("TPM: TlclGetRandom(%d)\n", length); 505 | memcpy(&cmd, &tpm_get_random_cmd, sizeof(cmd)); 506 | ToTpmUint32(cmd.buffer + tpm_get_random_cmd.bytesRequested, length); 507 | /* There must be room in the response buffer for the bytes. */ 508 | if (length > TPM_LARGE_ENOUGH_COMMAND_SIZE - kTpmResponseHeaderLength - sizeof(uint32_t)) { 509 | return TPM_E_IOERROR; 510 | } 511 | 512 | result = TlclSendReceive(cmd.buffer, response, sizeof(response)); 513 | if (result == TPM_SUCCESS) { 514 | uint8_t* get_random_cursor; 515 | FromTpmUint32(response + kTpmResponseHeaderLength, size); 516 | 517 | /* There must be room in the target buffer for the bytes. */ 518 | if (*size > length) { 519 | return TPM_E_RESPONSE_TOO_LARGE; 520 | } 521 | get_random_cursor = response + kTpmResponseHeaderLength + sizeof(uint32_t); 522 | memcpy(data, get_random_cursor, *size); 523 | } 524 | 525 | return result; 526 | } 527 | 528 | uint32_t TlclGetCapability(uint32_t capability, 529 | uint8_t *subCap, uint32_t subCapSize, 530 | uint8_t *response, uint32_t *responseSize) 531 | { 532 | uint32_t result; 533 | 534 | uint8_t command[TPM_LARGE_ENOUGH_COMMAND_SIZE] = {0x0, 0xc1}; 535 | uint8_t tempResponse[TPM_LARGE_ENOUGH_COMMAND_SIZE]; 536 | uint32_t size; 537 | 538 | /* Check for improper inputs */ 539 | if ((subCapSize > 0 && subCap == NULL) || response == NULL || responseSize == NULL) { 540 | return TPM_E_NULL_ARG; 541 | } 542 | 543 | size = 2 + 4 + 4 + TPM_U32_SIZE + TPM_U32_SIZE + subCapSize; 544 | ToTpmUint32(command + 2, size); 545 | ToTpmUint32(command + 6, 0x65); /* ordinal */ 546 | ToTpmUint32(command + 10, capability); 547 | ToTpmUint32(command + 14, subCapSize); 548 | if (subCapSize > 0) { 549 | memcpy(command + 18, subCap, subCapSize); 550 | } 551 | 552 | result = TlclSendReceive(command, tempResponse, sizeof(tempResponse)); 553 | 554 | if (result == TPM_SUCCESS) { 555 | FromTpmUint32(tempResponse + TPM_DATA_OFFSET, responseSize); 556 | memcpy(response, tempResponse + TPM_DATA_OFFSET + TPM_U32_SIZE, *responseSize); 557 | } 558 | 559 | return result; 560 | } 561 | 562 | uint32_t TlclTakeOwnership(uint8_t *ownerPass, uint8_t *srkPass) 563 | { 564 | uint32_t result; 565 | 566 | /*uint8_t nonceEven[TPM_HASH_SIZE]; 567 | uint8_t nonceOdd[TPM_HASH_SIZE]; 568 | uint8_t authData[TPM_HASH_SIZE]; 569 | 570 | uint32_t srkParamSize; 571 | uint32_t ownerEncSize, srkEncSize, authHandle;*/ 572 | 573 | /* need RSA encryption functions to continue */ 574 | result = 0; 575 | return result; 576 | } 577 | -------------------------------------------------------------------------------- /lib/tlcl/tlcl_hmac.c: -------------------------------------------------------------------------------- 1 | /* 2 | * tlcl: HMAC functions 3 | * Copyright (C) 2012 V Lab Technologies 4 | * Author: Teddy Reed 5 | * Based on libtpm by J. Kravitz (IBM) (C) 2004 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | */ 12 | 13 | #include 14 | 15 | #include 16 | #include "tlcl_internal.h" 17 | 18 | /* The user session and TPM authenticate each other using HMACs. 19 | * There is a required rolling set of odd, even nonces generated by the 20 | * user process and TPM which are updated for each new HMAC. 21 | * 22 | * The user session authenticates the TPM by verifying the returned HMAC 23 | * for a OSAP session which is keyed using the requested key handle. 24 | * The TPM authenticates the user session similarly when a command is used 25 | * with the returned OSAP handle, which must also include a keyed HMAC. 26 | * This process assures that both entities know can generate keyed HMACs 27 | * with the same AuthData. 28 | */ 29 | 30 | uint32_t TSS_CheckHMAC(const uint8_t *response, uint32_t command, 31 | const uint8_t *nonceOdd, const uint8_t *key, uint32_t keySize, 32 | const uint8_t *key2, uint32_t keySize2, ...) 33 | { 34 | uint16_t tag; /* AUTH1 or AUTH2 */ 35 | uint32_t size, offset; 36 | uint8_t ordinal[TPM_U32_SIZE]; 37 | 38 | uint8_t paramDigest[TPM_HASH_SIZE]; 39 | uint8_t authHmac[TPM_HASH_SIZE]; 40 | SHA1_CTX ctx; 41 | 42 | uint32_t arg_size, arg_pos; 43 | va_list argp; 44 | 45 | FromTpmUint16(response, &tag); 46 | FromTpmUint32(response + TPM_U16_SIZE, &size); 47 | ToTpmUint32(ordinal, command); 48 | 49 | if (tag == TPM_TAG_RSP_COMMAND) 50 | return TPM_SUCCESS; 51 | 52 | if (response == NULL || nonceOdd == NULL || key == NULL) 53 | return TPM_E_NULL_ARG; 54 | 55 | /* This can only check an AUTH1 or AUTH2 */ 56 | if (tag != TPM_TAG_RSP_AUTH1_COMMAND && tag != TPM_TAG_RSP_AUTH2_COMMAND) 57 | return TPM_E_HMAC_FAIL; 58 | 59 | /* If this is checking 2 auths, a second key is required */ 60 | if (tag == TPM_TAG_RSP_AUTH2_COMMAND && key2 == NULL) 61 | return TPM_E_NULL_ARG; 62 | 63 | /* HASH input */ 64 | sha1_starts(&ctx); 65 | sha1_update(&ctx, response + TPM_U16_SIZE + TPM_U32_SIZE, TPM_U32_SIZE); 66 | /* Check this: command should be TPM-endian? */ 67 | sha1_update(&ctx, ordinal, TPM_U32_SIZE); 68 | va_start(argp, keySize2); 69 | for (;;) { 70 | arg_size = (uint32_t) va_arg(argp, uint32_t); 71 | if (arg_size == 0) break; 72 | arg_pos = (uint32_t) va_arg(argp, uint32_t); 73 | sha1_update(&ctx, response + arg_pos, arg_size); 74 | } 75 | va_end(argp); 76 | sha1_finish(&ctx, paramDigest); 77 | 78 | /* Command trails with: 79 | * AUTH1: EVEN_NONCE, authBool, HMAC 80 | * AUTH2: EVEN_NONCE1, authBool1, HMAC1, EVEN_NONCE2, authBool2, HMAC2 81 | */ 82 | 83 | offset = TPM_NONCE_SIZE + 1 + TPM_HASH_SIZE; 84 | if (tag == TPM_TAG_RSP_AUTH2_COMMAND) 85 | offset *= 2; 86 | 87 | /* AUTH1 */ 88 | hmac_starts(&ctx, key, keySize); 89 | hmac_update(&ctx, paramDigest, TPM_HASH_SIZE); 90 | /* even nonce */ 91 | hmac_update(&ctx, response + size - offset, TPM_NONCE_SIZE); 92 | hmac_update(&ctx, nonceOdd, TPM_NONCE_SIZE); 93 | /* continue auth bool */ 94 | hmac_update(&ctx, response + size - offset + TPM_NONCE_SIZE, 1); 95 | hmac_finish(&ctx, key, keySize, authHmac); 96 | 97 | if (memcmp(authHmac, response + size - offset + TPM_NONCE_SIZE + 1, TPM_HASH_SIZE) != 0) 98 | return TPM_E_HMAC_FAIL; 99 | 100 | /* AUTH2 */ 101 | if (tag == TPM_TAG_RSP_AUTH2_COMMAND) { 102 | offset /= 2; 103 | hmac_starts(&ctx, key2, keySize2); 104 | hmac_update(&ctx, paramDigest, TPM_HASH_SIZE); 105 | /* even nonce */ 106 | hmac_update(&ctx, response + size - offset, TPM_NONCE_SIZE); 107 | hmac_update(&ctx, nonceOdd, TPM_NONCE_SIZE); 108 | /* continue auth bool */ 109 | hmac_update(&ctx, response + size - offset + TPM_NONCE_SIZE, 1); 110 | hmac_finish(&ctx, key2, keySize2, authHmac); 111 | 112 | if (memcmp(authHmac, response + size - offset + TPM_NONCE_SIZE + 1, TPM_HASH_SIZE) != 0) 113 | return TPM_E_HMAC_FAIL; 114 | } 115 | 116 | return TPM_SUCCESS; 117 | } 118 | 119 | uint32_t TSS_AuthHMAC(uint8_t *digest, 120 | const uint8_t *key, uint32_t keySize, const uint8_t *nonce1, const uint8_t *nonce2, 121 | uint8_t authBool, ...) 122 | { 123 | uint8_t paramDigest[TPM_HASH_SIZE]; 124 | SHA1_CTX ctx; 125 | 126 | uint32_t arg_size; 127 | uint8_t *arg_data; 128 | va_list argp; 129 | 130 | if (nonce1 == NULL || nonce2 == NULL) { 131 | return TPM_E_NULL_ARG; 132 | } 133 | 134 | /* HASH input */ 135 | sha1_starts(&ctx); 136 | va_start(argp, authBool); 137 | for (;;) { 138 | arg_size = (uint32_t) va_arg(argp, uint32_t); 139 | if (arg_size == 0) break; 140 | arg_data = (uint8_t *) va_arg(argp, uint32_t *); 141 | if (arg_data == NULL) 142 | return TPM_E_NULL_ARG; 143 | sha1_update(&ctx, arg_data, arg_size); 144 | } 145 | va_end(argp); 146 | sha1_finish(&ctx, paramDigest); 147 | 148 | /* Calculate HMAC */ 149 | hmac_starts(&ctx, key, keySize); 150 | hmac_update(&ctx, paramDigest, TPM_HASH_SIZE); 151 | hmac_update(&ctx, nonce1, TPM_NONCE_SIZE); 152 | hmac_update(&ctx, nonce2, TPM_NONCE_SIZE); 153 | hmac_update(&ctx, &authBool, 1); 154 | hmac_finish(&ctx, key, keySize, digest); 155 | 156 | return TPM_SUCCESS; 157 | } 158 | 159 | -------------------------------------------------------------------------------- /lib/tlcl/tlcl_internal.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 2 | * Use of this source code is governed by a BSD-style license that can be 3 | * found in the LICENSE file. 4 | */ 5 | 6 | #ifndef TPM_LITE_TLCL_INTERNAL_H_ 7 | #define TPM_LITE_TLCL_INTERNAL_H_ 8 | 9 | /* 10 | * These numbers derive from adding the sizes of command fields as shown in the 11 | * TPM commands manual. 12 | */ 13 | #define kTpmRequestHeaderLength 10 14 | #define kTpmResponseHeaderLength 10 15 | #define kTpmReadInfoLength 12 16 | #define kEncAuthLength 20 17 | #define kPcrDigestLength 20 18 | #define kWriteInfoLength 12 19 | #define kNvDataPublicPermissionsOffset 60 20 | 21 | #define TPM_MAX_BUFF_SIZE 4096 22 | #define TPM_HASH_SIZE 20 23 | #define TPM_NONCE_SIZE 20 24 | #define TPM_PCR_MASK_SIZE 2 25 | 26 | #define TPM_U16_SIZE 2 27 | #define TPM_U32_SIZE 4 28 | 29 | #define TPM_MAX_PCR_INFO_SIZE ( (TPM_HASH_SIZE * 2) + TPM_U16_SIZE + TPM_PCR_MASK_SIZE ) 30 | 31 | /* 32 | * Conversion functions. ToTpmTYPE puts a value of type TYPE into a TPM 33 | * command buffer. FromTpmTYPE gets a value of type TYPE from a TPM command 34 | * buffer into a variable. 35 | */ 36 | __attribute__((unused)) 37 | static inline void ToTpmUint32(uint8_t *buffer, uint32_t x) { 38 | buffer[0] = (uint8_t)(x >> 24); 39 | buffer[1] = (uint8_t)((x >> 16) & 0xff); 40 | buffer[2] = (uint8_t)((x >> 8) & 0xff); 41 | buffer[3] = (uint8_t)(x & 0xff); 42 | } 43 | 44 | /* 45 | * See comment for above function. 46 | */ 47 | __attribute__((unused)) 48 | static inline void FromTpmUint32(const uint8_t *buffer, uint32_t *x) { 49 | *x = ((buffer[0] << 24) | 50 | (buffer[1] << 16) | 51 | (buffer[2] << 8) | 52 | buffer[3]); 53 | } 54 | 55 | /* 56 | * See comment for above function. 57 | */ 58 | __attribute__((unused)) 59 | static inline void ToTpmUint16(uint8_t *buffer, uint16_t x) { 60 | buffer[0] = (uint8_t)(x >> 8); 61 | buffer[1] = (uint8_t)(x & 0xff); 62 | } 63 | 64 | /* 65 | * See comment for above function. 66 | */ 67 | __attribute__((unused)) 68 | static inline void FromTpmUint16(const uint8_t *buffer, uint16_t *x) { 69 | *x = (buffer[0] << 8) | buffer[1]; 70 | } 71 | 72 | /* The following HMAC functions are defined in tlcl_hmac */ 73 | 74 | /* Validate the HMAC for an AUTH1 or AUTH2 TPM response 75 | * response - pointer to response buffer 76 | * command - the 4byte command code generating the TPM reponse 77 | * nonceOdd - pointer to TPM_NONCE_SIZE byte array used in the request HMAC 78 | * key, keySize - the key used in the request HMAC 79 | * ... - a variable length set of argument pairs (length, offset) 80 | * they are an offset and length referring to the TPM response buffer 81 | * the last pair must be 0, 0. 82 | */ 83 | uint32_t TSS_CheckHMAC(const uint8_t *response, uint32_t command, 84 | const uint8_t *nonceOdd, 85 | const uint8_t *key, uint32_t keySize, const uint8_t *key2, uint32_t keySize2, ...); 86 | 87 | uint32_t TSS_AuthHMAC(uint8_t *digest, 88 | const uint8_t *key, uint32_t keySize, const uint8_t *nonce1, const uint8_t *nonce2, 89 | uint8_t authBool, ...); 90 | 91 | 92 | #endif /* TPM_LITE_TLCL_INTERNAL_H_ */ 93 | -------------------------------------------------------------------------------- /lib/tlcl/tlcl_keys.c: -------------------------------------------------------------------------------- 1 | /* 2 | * tlcl: Seal, Unseal 3 | * Copyright (C) 2012 V Lab Technologies 4 | * Author: Teddy Reed 5 | * Based on libtpm by J. Kravitz (IBM) (C) 2004 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | */ 12 | 13 | #include 14 | 15 | #include 16 | #include "tlcl_internal.h" 17 | #include "oiaposap.h" 18 | 19 | uint32_t TlclCreateWrapKey(uint32_t parentKeyHandle, uint8_t *parentKeyAuth, 20 | uint8_t *keyAuth, uint8_t *migrationAuth, 21 | Tlcl_KeyData *keyParams, Tlcl_KeyData *key, 22 | uint8_t *keyBlob, uint32_t *blobSize) 23 | { 24 | uint32_t result; 25 | 26 | uint8_t command[TPM_MAX_COMMAND_SIZE] = {0x0, 0xc2}; 27 | uint8_t response[TPM_MAX_COMMAND_SIZE]; 28 | uint8_t keyParamBuffer[TPM_MAX_COMMAND_SIZE]; 29 | uint8_t nonceOdd[TPM_NONCE_SIZE]; 30 | uint8_t xorWork[TPM_HASH_SIZE * 2]; 31 | uint8_t xorHash[TPM_HASH_SIZE]; 32 | uint8_t encAuth[TPM_HASH_SIZE], encAuth2[TPM_HASH_SIZE]; 33 | uint8_t authHmacDigest[TPM_HASH_SIZE], pubAuth[TPM_HASH_SIZE]; 34 | struct tss_osapsess sess; 35 | SHA1_CTX ctx; 36 | uint16_t keyType; 37 | uint32_t size, keyParamBufferSize; 38 | uint32_t i; 39 | uint8_t c, tpm_hmac_data[TPM_U32_SIZE]; 40 | 41 | /* Must provide keyParams, and keyAuth/partentAuth (0's for well-known) */ 42 | if (keyParams == NULL || keyAuth == NULL || parentKeyAuth == NULL) { 43 | return TPM_E_NULL_ARG; 44 | } 45 | 46 | /* Only type 1 keys for now */ 47 | keyType = 0x0001; 48 | 49 | /* Add TPM version to keyParams */ 50 | result = TlclGetCapability(0x00000006, NULL, 0, &(keyParams->version[0]), &size); 51 | if (result != TPM_SUCCESS) { 52 | return result; 53 | } 54 | 55 | /* Generate Odd Nonce */ 56 | TlclGetRandom(nonceOdd, TPM_NONCE_SIZE, &size); 57 | 58 | /* Open OSAP session */ 59 | result = TSS_OSAPopen(&sess, parentKeyAuth, keyType, parentKeyHandle); 60 | if (result != TPM_SUCCESS) { 61 | return result; 62 | } 63 | 64 | /* Calculate encrypted authorization value for new key */ 65 | memcpy(xorWork, sess.ssecret, TPM_HASH_SIZE); 66 | memcpy(xorWork + TPM_HASH_SIZE, sess.enonce, TPM_HASH_SIZE); 67 | sha1_starts(&ctx); 68 | sha1_update(&ctx, xorWork, TPM_HASH_SIZE * 2); 69 | sha1_finish(&ctx, xorHash); 70 | 71 | for (i = 0; i < TPM_HASH_SIZE; ++i) { 72 | encAuth[i] = xorHash[i] ^ keyAuth[i]; 73 | } 74 | 75 | if (migrationAuth != NULL) { 76 | /* Calculate encrypted authorization value for migration of new key */ 77 | memcpy(xorWork, sess.ssecret, TPM_HASH_SIZE); 78 | memcpy(xorWork + TPM_HASH_SIZE, nonceOdd, TPM_HASH_SIZE); 79 | sha1_starts(&ctx); 80 | sha1_update(&ctx, xorWork, TPM_HASH_SIZE * 2); 81 | sha1_finish(&ctx, xorHash); 82 | 83 | for (i = 0; i < TPM_HASH_SIZE; ++i) { 84 | encAuth2[i] = xorHash[i] ^ migrationAuth[i]; 85 | } 86 | } else { 87 | memset(encAuth2, 0, TPM_HASH_SIZE); 88 | } 89 | memset(xorWork, 0, TPM_HASH_SIZE * 2); 90 | memset(xorHash, 0, TPM_HASH_SIZE); 91 | 92 | /* Convert keyParam to command buffer */ 93 | memcpy(keyParamBuffer, keyParams->version, 4); 94 | ToTpmUint16(keyParamBuffer + 4, keyParams->keyusage); 95 | ToTpmUint32(keyParamBuffer + 6, keyParams->keyflags); 96 | memset(keyParamBuffer + 10, keyParams->authdatausage, 1); 97 | ToTpmUint32(keyParamBuffer + 11, keyParams->pub.algorithm); 98 | ToTpmUint16(keyParamBuffer + 15, keyParams->pub.encscheme); 99 | ToTpmUint16(keyParamBuffer + 17, keyParams->pub.sigscheme); 100 | ToTpmUint32(keyParamBuffer + 19, 12); 101 | ToTpmUint32(keyParamBuffer + 23, keyParams->pub.keybitlen); 102 | ToTpmUint32(keyParamBuffer + 27, keyParams->pub.numprimes); 103 | ToTpmUint32(keyParamBuffer + 31, 0); 104 | ToTpmUint32(keyParamBuffer + 35, keyParams->pub.pcrinfolen); 105 | memcpy(keyParamBuffer + 39, keyParams->pub.pcrinfo, keyParams->pub.pcrinfolen); 106 | ToTpmUint32(keyParamBuffer + 39 + keyParams->pub.pcrinfolen, keyParams->pub.keylength); 107 | memcpy(keyParamBuffer + 43 + keyParams->pub.pcrinfolen, keyParams->pub.modulus, keyParams->pub.keylength); 108 | ToTpmUint32(keyParamBuffer + 43 + keyParams->pub.pcrinfolen + keyParams->pub.keylength, keyParams->privkeylen); 109 | memcpy(keyParamBuffer + 47 + keyParams->pub.pcrinfolen + keyParams->pub.keylength, keyParams->encprivkey, keyParams->privkeylen); 110 | /* Set keyParam buffer size */ 111 | keyParamBufferSize = 47 + keyParams->pub.pcrinfolen + keyParams->pub.keylength + keyParams->privkeylen; 112 | 113 | debug("keyParamBuffer size: %d\n", keyParamBufferSize); 114 | 115 | /* Calculate authorization HMAC */ 116 | c = 0; 117 | sha1_starts(&ctx); 118 | ToTpmUint32(tpm_hmac_data, 0x1f); /* could be 1f */ 119 | sha1_update(&ctx, tpm_hmac_data, TPM_U32_SIZE); 120 | sha1_update(&ctx, encAuth, TPM_HASH_SIZE); 121 | sha1_update(&ctx, encAuth2, TPM_HASH_SIZE); 122 | sha1_update(&ctx, keyParamBuffer, keyParamBufferSize); 123 | sha1_finish(&ctx, authHmacDigest); 124 | /*memset(encAuth, 0, TPM_HASH_SIZE); 125 | memset(encAuth2, 0, TPM_HASH_SIZE);*/ 126 | 127 | hmac_starts(&ctx, sess.ssecret, TPM_HASH_SIZE); 128 | hmac_update(&ctx, authHmacDigest, TPM_HASH_SIZE); 129 | hmac_update(&ctx, sess.enonce, TPM_NONCE_SIZE); 130 | hmac_update(&ctx, nonceOdd, TPM_NONCE_SIZE); 131 | hmac_update(&ctx, &c, 1); 132 | hmac_finish(&ctx, sess.ssecret, TPM_HASH_SIZE, pubAuth); 133 | 134 | /* Build the command */ 135 | size = 2 + TPM_U32_SIZE * 3 /* size, keyHandle */ + TPM_HASH_SIZE * 2 + 136 | keyParamBufferSize + TPM_U32_SIZE /* sess.handle */ + TPM_NONCE_SIZE + 137 | 1 + TPM_HASH_SIZE; 138 | ToTpmUint32(command + 2, size); 139 | ToTpmUint32(command + 6, 0x1f); /* ordinal */ 140 | ToTpmUint32(command + 10, parentKeyHandle); 141 | memcpy(command + 14, encAuth, TPM_HASH_SIZE); 142 | memcpy(command + 14 + TPM_HASH_SIZE, encAuth2, TPM_HASH_SIZE); 143 | memcpy(command + 14 + TPM_HASH_SIZE * 2, keyParamBuffer, keyParamBufferSize); 144 | ToTpmUint32(command + 14 + TPM_HASH_SIZE * 2 + keyParamBufferSize, sess.handle); 145 | memcpy(command + 18 + TPM_HASH_SIZE * 2 + keyParamBufferSize, nonceOdd, TPM_NONCE_SIZE); 146 | memset(command + 18 + TPM_HASH_SIZE * 2 + keyParamBufferSize + TPM_NONCE_SIZE, c, 1); 147 | memcpy(command + 19 + TPM_HASH_SIZE * 2 + keyParamBufferSize + TPM_NONCE_SIZE, pubAuth, TPM_HASH_SIZE); 148 | 149 | /* Transmit command, receive response */ 150 | result = TlclSendReceive(command, response, sizeof(response)); 151 | 152 | 153 | return result; 154 | } 155 | 156 | -------------------------------------------------------------------------------- /lib/tlcl/tlcl_seal.c: -------------------------------------------------------------------------------- 1 | /* 2 | * tlcl: Seal, Unseal 3 | * Copyright (C) 2012 V Lab Technologies 4 | * Author: Teddy Reed 5 | * Based on libtpm by J. Kravitz (IBM) (C) 2004 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | */ 12 | 13 | #include 14 | #include 15 | 16 | #include 17 | #include "tlcl_internal.h" 18 | #include "oiaposap.h" 19 | 20 | /* tpm seal/unseal commands */ 21 | 22 | uint32_t TlclSeal(uint32_t keyHandle, 23 | const uint8_t *pcrInfo, uint32_t pcrInfoSize, 24 | const uint8_t *keyAuth, const uint8_t *dataAuth, 25 | const uint8_t *data, uint32_t dataSize, 26 | uint8_t *blob, uint32_t *blobSize) 27 | { 28 | uint16_t i; 29 | uint32_t result; 30 | uint8_t command[TPM_MAX_COMMAND_SIZE] = {0x0, 0xC2}; 31 | uint8_t response[TPM_MAX_COMMAND_SIZE]; 32 | 33 | struct tss_osapsess sess; 34 | uint8_t encAuth[TPM_HASH_SIZE]; 35 | uint8_t pubAuth[TPM_HASH_SIZE]; 36 | uint32_t size, sealInfoSize, encDataSize, storedSize; 37 | uint8_t nonceOdd[TPM_NONCE_SIZE]; 38 | 39 | /* might not use */ 40 | uint8_t xorWork[TPM_HASH_SIZE * 2]; 41 | uint8_t xorHash[TPM_HASH_SIZE]; 42 | SHA1_CTX ctx; 43 | 44 | uint16_t keyType; /* for keyHandle */ 45 | 46 | /* TPM (big-endian data) for authentication HMAC */ 47 | uint8_t tpm_hmac_data[TPM_U32_SIZE]; 48 | uint8_t authHmacDigest[TPM_HASH_SIZE]; 49 | uint8_t c; 50 | 51 | /* Input data checking */ 52 | if (data == NULL || blob == NULL) { 53 | /* Todo: return error */ 54 | return TPM_E_NULL_ARG; /* EINVAL */ 55 | } 56 | if (pcrInfoSize != 0 && pcrInfo == NULL) { 57 | /* Todo: return error */ 58 | return TPM_E_NULL_ARG; /* EINVAL */ 59 | } 60 | 61 | if (keyHandle == 0x40000000) { 62 | keyType = 0x0004; 63 | debug("TPM: seal using SRK.\n"); 64 | } else { 65 | keyType = 0x0001; 66 | } 67 | /* handle null auth for key and data, for now only use non-null passwords */ 68 | /* assert(keyAuth != NULL && dataAuth != NULL); */ 69 | 70 | result = TSS_OSAPopen(&sess, keyAuth, keyType, keyHandle); 71 | if (result != TPM_SUCCESS) { 72 | /* This will fail is key does not exist or TPM has not run TakeOwnership. */ 73 | debug("TPM: TSS_OSAPopen failed\n"); 74 | return result; 75 | } 76 | 77 | /* calculate encrypted authorization value */ 78 | memcpy(xorWork, sess.ssecret, TPM_HASH_SIZE); 79 | memcpy(xorWork + TPM_HASH_SIZE, sess.enonce, TPM_HASH_SIZE); 80 | sha1_starts(&ctx); 81 | sha1_update(&ctx, xorWork, TPM_HASH_SIZE * 2); 82 | sha1_finish(&ctx, xorHash); 83 | memset(xorWork, 0, TPM_HASH_SIZE * 2); 84 | 85 | /* generate odd nonce */ 86 | TlclGetRandom(nonceOdd, TPM_NONCE_SIZE, &size); 87 | 88 | /* encrypt data authorization key, expects dataAuth to be as hash */ 89 | for (i = 0; i < TPM_HASH_SIZE; ++i) { 90 | encAuth[i] = xorHash[i] ^ dataAuth[i]; 91 | } 92 | memset(xorHash, 0, TPM_HASH_SIZE); 93 | 94 | /* calculate authorization HMAC */ 95 | c = 0; 96 | sha1_starts(&ctx); 97 | ToTpmUint32(tpm_hmac_data, 0x17); 98 | sha1_update(&ctx, tpm_hmac_data, TPM_U32_SIZE); 99 | sha1_update(&ctx, encAuth, TPM_HASH_SIZE); 100 | ToTpmUint32(tpm_hmac_data, pcrInfoSize); 101 | sha1_update(&ctx, tpm_hmac_data, TPM_U32_SIZE); 102 | if (pcrInfoSize > 0) { 103 | /* PCRs */ 104 | sha1_update(&ctx, pcrInfo, pcrInfoSize); 105 | /* this time include pcrInfo */ 106 | } 107 | ToTpmUint32(tpm_hmac_data, dataSize); 108 | sha1_update(&ctx, tpm_hmac_data, TPM_U32_SIZE); 109 | sha1_update(&ctx, data, dataSize); 110 | sha1_finish(&ctx, authHmacDigest); 111 | 112 | hmac_starts(&ctx, sess.ssecret, TPM_HASH_SIZE); 113 | hmac_update(&ctx, authHmacDigest, TPM_HASH_SIZE); 114 | hmac_update(&ctx, sess.enonce, TPM_NONCE_SIZE); 115 | hmac_update(&ctx, nonceOdd, TPM_NONCE_SIZE); 116 | hmac_update(&ctx, &c, 1); 117 | hmac_finish(&ctx, sess.ssecret, TPM_HASH_SIZE, pubAuth); 118 | 119 | /* Build command */ 120 | size = 2 /*tag*/ + 12 /*paramSize,ordinal,keyHandle*/ + TPM_HASH_SIZE /*encAuth*/ + 121 | pcrInfoSize + 4 /*size included*/ + dataSize + 4 + 4 /*authHandle*/ + TPM_NONCE_SIZE + 122 | 1 /*authSess bool*/ + TPM_HASH_SIZE; 123 | ToTpmUint32(command + 2, size); 124 | ToTpmUint32(command + 6, 0x17); 125 | ToTpmUint32(command + 10, keyHandle); 126 | memcpy(command + 14, encAuth, TPM_HASH_SIZE); 127 | ToTpmUint32(command + 14 + TPM_HASH_SIZE, pcrInfoSize); 128 | if (pcrInfoSize > 0) { 129 | memcpy(command + 18 + TPM_HASH_SIZE, pcrInfo, pcrInfoSize); 130 | } 131 | ToTpmUint32(command + 18 + TPM_HASH_SIZE + pcrInfoSize, dataSize); 132 | memcpy(command + 22 + TPM_HASH_SIZE + pcrInfoSize, data, dataSize); 133 | ToTpmUint32(command + 22 + TPM_HASH_SIZE + pcrInfoSize + dataSize, sess.handle); 134 | memcpy(command + 26 + TPM_HASH_SIZE + pcrInfoSize + dataSize, nonceOdd, TPM_NONCE_SIZE); 135 | memset(command + 26 + TPM_HASH_SIZE + pcrInfoSize + dataSize + TPM_NONCE_SIZE, 0, 1); 136 | memcpy(command + 27 + TPM_HASH_SIZE + pcrInfoSize + dataSize + TPM_NONCE_SIZE, pubAuth, TPM_HASH_SIZE); 137 | 138 | /* send command */ 139 | result = TlclSendReceive(command, response, sizeof(response)); 140 | 141 | if (result == TPM_SUCCESS) { 142 | /* first 32bit after the header is the size of return */ 143 | FromTpmUint32(response + kTpmResponseHeaderLength, &size); 144 | FromTpmUint32(response + kTpmResponseHeaderLength + TPM_U32_SIZE, &sealInfoSize); 145 | debug("TPM: seal info size: %d\n", sealInfoSize); 146 | FromTpmUint32(response + kTpmResponseHeaderLength + TPM_U32_SIZE + TPM_U32_SIZE + sealInfoSize, &encDataSize); 147 | debug("TPM: enc data size: %d\n", encDataSize); 148 | storedSize = TPM_U32_SIZE * 3 + sealInfoSize + encDataSize; 149 | debug("TPM: stored size: %d\n", storedSize); 150 | 151 | /* check HMAC */ 152 | result = TSS_CheckHMAC(response, 0x17, nonceOdd, sess.ssecret, TPM_HASH_SIZE, NULL, 0, storedSize, TPM_DATA_OFFSET, 0, 0); 153 | 154 | /* set output param values */ 155 | memcpy(blob, response + kTpmResponseHeaderLength, storedSize); 156 | *blobSize = storedSize; 157 | } else { 158 | /* Todo: check if OSAP is closed upon success */ 159 | TSS_OSAPclose(&sess); 160 | } 161 | 162 | return result; 163 | } 164 | 165 | uint32_t TSS_GenPCRInfo(uint32_t pcrMap, uint8_t *pcrInfo, uint32_t *size) 166 | { 167 | uint32_t result; 168 | 169 | struct pcrInfo { 170 | uint8_t selSize[TPM_U16_SIZE]; /* uint16_t */ 171 | uint8_t select[TPM_PCR_MASK_SIZE]; 172 | uint8_t relHash[TPM_HASH_SIZE]; 173 | uint8_t crtHash[TPM_HASH_SIZE]; 174 | } info; 175 | 176 | uint16_t i, j, numRegs; 177 | uint32_t pcrMapTemp; 178 | uint8_t *pcrValues, valueSize[TPM_U32_SIZE]; 179 | SHA1_CTX ctx; 180 | 181 | /* must be valid pointers */ 182 | if (pcrInfo == NULL || size == NULL) { 183 | return TPM_E_NULL_ARG; 184 | } 185 | 186 | /* build PCR selection matrix */ 187 | pcrMapTemp = pcrMap; 188 | memset(info.select, 0, TPM_PCR_MASK_SIZE); 189 | for (i = 0; i < TPM_PCR_MASK_SIZE; ++i) { 190 | info.select[i] = pcrMapTemp & 0x000000FF; 191 | pcrMapTemp = pcrMapTemp >> 8; 192 | } 193 | 194 | /* calculate number of PCR registers requested */ 195 | numRegs = 0; 196 | pcrMapTemp = pcrMap; 197 | for (i = 0; i < (TPM_PCR_MASK_SIZE * 8); ++i) { 198 | if (pcrMapTemp & 1) ++numRegs; 199 | pcrMapTemp = pcrMapTemp >> 1; 200 | } 201 | 202 | /* check for 0 registers */ 203 | if (numRegs == 0) { 204 | *size = 0; 205 | return 0; 206 | } 207 | 208 | /* create a matrix of PCR values */ 209 | pcrValues = (uint8_t *) malloc(TPM_HASH_SIZE * numRegs); 210 | pcrMapTemp = pcrMap; 211 | for (i = 0, j = 0; i < (TPM_PCR_MASK_SIZE * 8); ++i, pcrMapTemp = pcrMapTemp >> 1) { 212 | if ((pcrMapTemp & 1) == 0) continue; 213 | result = TlclPCRRead(i, &(pcrValues[(j * TPM_HASH_SIZE)]), kPcrDigestLength); 214 | if (result != TPM_SUCCESS) { 215 | /* todo: print trace */ 216 | return result; 217 | } 218 | ++j; 219 | } 220 | 221 | ToTpmUint16(info.selSize, TPM_PCR_MASK_SIZE); 222 | ToTpmUint32(valueSize, numRegs * TPM_HASH_SIZE); 223 | 224 | /* composite hash of selected PCR values */ 225 | sha1_starts(&ctx); 226 | sha1_update(&ctx, info.selSize, TPM_U16_SIZE); 227 | sha1_update(&ctx, info.select, TPM_PCR_MASK_SIZE); 228 | sha1_update(&ctx, valueSize, TPM_U32_SIZE); 229 | for (i = 0; i < numRegs; ++i) { 230 | sha1_update(&ctx, &(pcrValues[(i * TPM_HASH_SIZE)]), TPM_HASH_SIZE); 231 | } 232 | sha1_finish(&ctx, info.relHash); 233 | memcpy(info.crtHash, info.relHash, TPM_HASH_SIZE); 234 | 235 | /* copy to input params */ 236 | memcpy(pcrInfo, &info, sizeof(struct pcrInfo)); 237 | *size = sizeof(struct pcrInfo); 238 | 239 | return TPM_SUCCESS; 240 | } 241 | 242 | 243 | uint32_t TlclSealPCR(uint32_t keyHandle, uint32_t pcrMap, 244 | const uint8_t *keyAuth, const uint8_t *dataAuth, 245 | const uint8_t *data, uint32_t dataSize, 246 | uint8_t *blob, uint32_t *blobSize) 247 | { 248 | uint32_t result; 249 | 250 | uint8_t pcrInfo[TPM_MAX_PCR_INFO_SIZE]; 251 | uint32_t pcrSize; 252 | 253 | result = TSS_GenPCRInfo(pcrMap, pcrInfo, &pcrSize); 254 | if (result != TPM_SUCCESS) { 255 | return result; 256 | } 257 | 258 | return TlclSeal(keyHandle, pcrInfo, pcrSize, keyAuth, dataAuth, data, 259 | dataSize, blob, blobSize); 260 | } 261 | 262 | uint32_t TlclUnseal(uint32_t keyHandle, 263 | const uint8_t *keyAuth, const uint8_t *dataAuth, 264 | const uint8_t *blob, uint32_t blobSize, 265 | uint8_t *rawData, uint32_t *dataSize) 266 | { 267 | uint32_t result; 268 | uint8_t command[TPM_MAX_COMMAND_SIZE] = {0x0, 0xC3}; 269 | uint8_t response[TPM_MAX_COMMAND_SIZE]; 270 | 271 | uint32_t keyAuthHandle, dataAuthHandle, size; 272 | uint8_t keyAuthData[TPM_HASH_SIZE], dataAuthData[TPM_HASH_SIZE]; 273 | uint8_t enonceKey[TPM_NONCE_SIZE], enonceData[TPM_NONCE_SIZE]; 274 | uint8_t nonceOdd[TPM_NONCE_SIZE]; 275 | uint8_t authHmacDigest[TPM_HASH_SIZE]; 276 | uint8_t c, offset; 277 | SHA1_CTX ctx; 278 | 279 | /* used to convert host-endianess to TPM-endianess (big) */ 280 | uint8_t tpm_hmac_data[TPM_U32_SIZE]; 281 | 282 | /* check input params */ 283 | if (rawData == NULL || blob == NULL) { 284 | return TPM_E_NULL_ARG; 285 | } 286 | 287 | /* Data auth is required, key may not require auth. */ 288 | if (keyAuth != NULL) { 289 | result = TSS_OIAPopen(&keyAuthHandle, enonceKey); 290 | if (result != TPM_SUCCESS) { 291 | return result; 292 | } 293 | } 294 | result = TSS_OIAPopen(&dataAuthHandle, enonceData); 295 | if (result != TPM_SUCCESS) { 296 | return result; 297 | } 298 | 299 | /* generate odd nonce */ 300 | TlclGetRandom(nonceOdd, TPM_NONCE_SIZE, &size); 301 | /* todo: is it OK to use the same odd nonce? */ 302 | 303 | c = 0; 304 | ToTpmUint32(tpm_hmac_data, 0x18); 305 | /* calculate key authorization HMAC */ 306 | sha1_starts(&ctx); 307 | sha1_update(&ctx, tpm_hmac_data, TPM_U32_SIZE); 308 | sha1_update(&ctx, blob, blobSize); 309 | sha1_finish(&ctx, authHmacDigest); 310 | 311 | /* Again, key auth may not be required */ 312 | if (keyAuth != NULL) { 313 | hmac_starts(&ctx, keyAuth, TPM_HASH_SIZE); 314 | hmac_update(&ctx, authHmacDigest, TPM_HASH_SIZE); 315 | hmac_update(&ctx, enonceKey, TPM_NONCE_SIZE); 316 | hmac_update(&ctx, nonceOdd, TPM_NONCE_SIZE); 317 | hmac_update(&ctx, &c, 1); 318 | hmac_finish(&ctx, keyAuth, TPM_HASH_SIZE, keyAuthData); 319 | } 320 | 321 | /* calculate data authorization HMAC */ 322 | hmac_starts(&ctx, dataAuth, TPM_HASH_SIZE); 323 | hmac_update(&ctx, authHmacDigest, TPM_HASH_SIZE); 324 | hmac_update(&ctx, enonceData, TPM_NONCE_SIZE); 325 | hmac_update(&ctx, nonceOdd, TPM_NONCE_SIZE); 326 | hmac_update(&ctx, &c, 1); 327 | hmac_finish(&ctx, dataAuth, TPM_HASH_SIZE, dataAuthData); 328 | 329 | /* build command buffer */ 330 | size = 2 /*tag*/ + TPM_U32_SIZE * 3 /*paramSize, ordinal, keyHandle*/ + 331 | TPM_U32_SIZE + TPM_NONCE_SIZE + 1 + TPM_HASH_SIZE + 332 | blobSize + TPM_U32_SIZE + TPM_NONCE_SIZE + 1 + TPM_HASH_SIZE; 333 | 334 | if (keyAuth == NULL) { 335 | size -= (TPM_U32_SIZE + TPM_NONCE_SIZE + 1 + TPM_HASH_SIZE); 336 | memset(command, 0x00, 1); 337 | memset(command + 1, 0xc2, 1); /* only 1 authHandle */ 338 | } 339 | 340 | ToTpmUint32(command + 2, size); 341 | ToTpmUint32(command + 6, 0x18); 342 | ToTpmUint32(command + 10, keyHandle); 343 | 344 | /* Blob contains flags and size of sealed data */ 345 | memcpy(command + 14, blob, blobSize); 346 | 347 | /* key auth params: handle, nonceOdd, continue_bool, keyAuthHMAC */ 348 | offset = 0; 349 | if (keyAuth != NULL) { 350 | ToTpmUint32(command + 14 + blobSize, keyAuthHandle); 351 | memcpy(command + 18 + blobSize, nonceOdd, TPM_NONCE_SIZE); 352 | memcpy(command + 18 + blobSize + TPM_NONCE_SIZE, &c, 1); 353 | memcpy(command + 19 + blobSize + TPM_NONCE_SIZE, keyAuthData, TPM_HASH_SIZE); 354 | offset += TPM_U32_SIZE + TPM_NONCE_SIZE + 1 + TPM_HASH_SIZE; 355 | } 356 | 357 | /* data auth params: handle, nonceOdd, continue_bool, dataAuthHMAC */ 358 | ToTpmUint32(command + 14 + blobSize + offset, dataAuthHandle); 359 | memcpy(command + 18 + blobSize + offset, nonceOdd, TPM_NONCE_SIZE); 360 | memcpy(command + 18 + blobSize + offset + TPM_NONCE_SIZE , &c, 1); 361 | memcpy(command + 19 + blobSize + offset + TPM_NONCE_SIZE, dataAuthData, TPM_HASH_SIZE); 362 | 363 | /* send command */ 364 | result = TlclSendReceive(command, response, sizeof(response)); 365 | 366 | if (result == TPM_SUCCESS) { 367 | /* first 32bit after the header is the size of return */ 368 | /* size of returned data blob */ 369 | FromTpmUint32(response + kTpmResponseHeaderLength, dataSize); 370 | 371 | /* check HMAC */ 372 | if (keyAuth != NULL) { 373 | /* key + data password, AUTH2 */ 374 | result = TSS_CheckHMAC(response, 0x18, nonceOdd, 375 | keyAuth, TPM_HASH_SIZE, dataAuth, TPM_HASH_SIZE, 376 | TPM_U32_SIZE, TPM_DATA_OFFSET, 377 | *dataSize, TPM_DATA_OFFSET + TPM_U32_SIZE, 0, 0); 378 | } else { 379 | /* data password, AUTH1 */ 380 | result = TSS_CheckHMAC(response, 0x18, nonceOdd, 381 | dataAuth, TPM_HASH_SIZE, NULL, 0, 382 | TPM_U32_SIZE, TPM_DATA_OFFSET, 383 | *dataSize, TPM_DATA_OFFSET + TPM_U32_SIZE, 0, 0); 384 | } 385 | 386 | /* set output param values */ 387 | memcpy(rawData, response + kTpmResponseHeaderLength + TPM_U32_SIZE, *dataSize); 388 | } else { 389 | /* OIAP sessions should close on success */ 390 | if (keyAuth != NULL) { 391 | TSS_OIAPclose(keyAuthHandle); 392 | } 393 | TSS_OIAPclose(dataAuthHandle); 394 | } 395 | 396 | return result; 397 | } 398 | -------------------------------------------------------------------------------- /lib/tlcl/tlcl_seal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * tlcl: Seal, Unseal 3 | * Copyright (C) 2012 V Lab Technologies 4 | * Author: Teddy Reed 5 | * Based on libtpm by J. Kravitz (IBM) (C) 2004 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | */ 12 | 13 | #ifndef TLCL_SEAL_H_ 14 | #define TLCL_SEAL_H_ 15 | 16 | 17 | 18 | 19 | #endif /* TLCL_SEAL_H_ */ 20 | -------------------------------------------------------------------------------- /lib/tlcl/tlcl_structures.h: -------------------------------------------------------------------------------- 1 | /* This file is NOT automatically generated :) */ 2 | 3 | #ifndef TPM_LITE_TLCL_STRUCTURES_H_ 4 | #define TPM_LITE_TLCL_STRUCTURES_H_ 5 | 6 | const struct s_tpm_extend_cmd{ 7 | uint8_t buffer[34]; 8 | uint16_t pcrNum; 9 | uint16_t inDigest; 10 | } tpm_extend_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x14, }, 11 | 10, 14, }; 12 | 13 | const struct s_tpm_get_random_cmd{ 14 | uint8_t buffer[14]; 15 | uint16_t bytesRequested; 16 | } tpm_get_random_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x46, }, 17 | 10, }; 18 | 19 | const struct s_tpm_getownership_cmd{ 20 | uint8_t buffer[22]; 21 | } tpm_getownership_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0x65, 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x1, 0x11, }, 22 | }; 23 | 24 | const struct s_tpm_getpermissions_cmd{ 25 | uint8_t buffer[22]; 26 | uint16_t index; 27 | } tpm_getpermissions_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0x65, 0x0, 0x0, 0x0, 0x11, 0x0, 0x0, 0x0, 0x4, }, 28 | 18, }; 29 | 30 | const struct s_tpm_getstclearflags_cmd{ 31 | uint8_t buffer[22]; 32 | } tpm_getstclearflags_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0x65, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x1, 0x9, }, 33 | }; 34 | 35 | const struct s_tpm_getflags_cmd{ 36 | uint8_t buffer[22]; 37 | } tpm_getflags_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0x65, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x1, 0x8, }, 38 | }; 39 | 40 | const struct s_tpm_physicalsetdeactivated_cmd{ 41 | uint8_t buffer[11]; 42 | uint16_t deactivated; 43 | } tpm_physicalsetdeactivated_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x72, }, 44 | 10, }; 45 | 46 | const struct s_tpm_physicalenable_cmd{ 47 | uint8_t buffer[10]; 48 | } tpm_physicalenable_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f, }, 49 | }; 50 | 51 | const struct s_tpm_physicaldisable_cmd{ 52 | uint8_t buffer[10]; 53 | } tpm_physicaldisable_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70, }, 54 | }; 55 | 56 | const struct s_tpm_forceclear_cmd{ 57 | uint8_t buffer[10]; 58 | } tpm_forceclear_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d, }, 59 | }; 60 | 61 | const struct s_tpm_readpubek_cmd{ 62 | uint8_t buffer[30]; 63 | } tpm_readpubek_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x7c, }, 64 | }; 65 | 66 | const struct s_tpm_reset_cmd { 67 | uint8_t buffer[10]; 68 | } tpm_reset_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5a}}; 69 | 70 | const struct s_tpm_continueselftest_cmd{ 71 | uint8_t buffer[10]; 72 | } tpm_continueselftest_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53, }, 73 | }; 74 | 75 | const struct s_tpm_selftestfull_cmd{ 76 | uint8_t buffer[10]; 77 | } tpm_selftestfull_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50, }, 78 | }; 79 | 80 | const struct s_tpm_resume_cmd{ 81 | uint8_t buffer[12]; 82 | } tpm_resume_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x2, }, 83 | }; 84 | 85 | const struct s_tpm_savestate_cmd{ 86 | uint8_t buffer[10]; 87 | } tpm_savestate_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x98, }, 88 | }; 89 | 90 | const struct s_tpm_startup_cmd{ 91 | uint8_t buffer[12]; 92 | } tpm_startup_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x1, }, 93 | }; 94 | 95 | const struct s_tpm_finalizepp_cmd{ 96 | uint8_t buffer[12]; 97 | } tpm_finalizepp_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x2, 0xa0, }, 98 | }; 99 | 100 | const struct s_tpm_pplock_cmd{ 101 | uint8_t buffer[12]; 102 | } tpm_pplock_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x4, }, 103 | }; 104 | 105 | const struct s_tpm_ppenable_cmd{ 106 | uint8_t buffer[12]; 107 | } tpm_ppenable_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x20, }, 108 | }; 109 | 110 | const struct s_tpm_ppassert_cmd{ 111 | uint8_t buffer[12]; 112 | } tpm_ppassert_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x8, }, 113 | }; 114 | 115 | const struct s_tpm_pcr_read_cmd{ 116 | uint8_t buffer[14]; 117 | uint16_t pcrNum; 118 | } tpm_pcr_read_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x15, }, 119 | 10, }; 120 | 121 | const struct s_tpm_nv_read_cmd{ 122 | uint8_t buffer[22]; 123 | uint16_t index; 124 | uint16_t length; 125 | } tpm_nv_read_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0xcf, }, 126 | 10, 18, }; 127 | 128 | const struct s_tpm_nv_write_cmd{ 129 | uint8_t buffer[512]; 130 | uint16_t index; 131 | uint16_t length; 132 | uint16_t data; 133 | } tpm_nv_write_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd, }, 134 | 10, 18, 22, }; 135 | 136 | const struct s_tpm_nv_definespace_cmd{ 137 | uint8_t buffer[101]; 138 | uint16_t index; 139 | uint16_t perm; 140 | uint16_t size; 141 | } tpm_nv_definespace_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x65, 0x0, 0x0, 0x0, 0xcc, 0x0, 0x18, 0, 0, 0, 0, 0x0, 0x3, 0, 0, 0, 0x1f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0, 0x3, 0, 0, 0, 0x1f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0, 0x17, }, 142 | 12, 70, 77, }; 143 | 144 | #endif 145 | -------------------------------------------------------------------------------- /lib/tlcl/tpm_error_messages.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 2 | * Use of this source code is governed by a BSD-style license that can be 3 | * found in the LICENSE file. 4 | */ 5 | 6 | /* TPM error codes. 7 | * 8 | * Copy-pasted and lightly edited from TCG TPM Main Part 2 TPM Structures 9 | * Version 1.2 Level 2 Revision 103 26 October 2006 Draft. 10 | */ 11 | 12 | #ifndef TPM_ERROR_MESSAGES_H 13 | #define TPM_ERROR_MESSAGES_H 14 | 15 | #define TPM_E_BASE 0x0 16 | #define TPM_E_NON_FATAL 0x800 17 | 18 | typedef struct tpm_error_info { 19 | const char* name; 20 | uint32_t code; 21 | const char* description; 22 | } tpm_error_info; 23 | 24 | tpm_error_info tpm_error_table[] = { 25 | { "TPM_AUTHFAIL", TPM_E_BASE + 1, 26 | "Authentication failed" }, 27 | { "TPM_BADINDEX", TPM_E_BASE + 2, 28 | "The index to a PCR, DIR or other register is incorrect" }, 29 | { "TPM_BAD_PARAMETER", TPM_E_BASE + 3, 30 | "One or more parameter is bad" }, 31 | { "TPM_AUDITFAILURE", TPM_E_BASE + 4, 32 | "An operation completed successfully\n\ 33 | but the auditing of that operation failed" }, 34 | { "TPM_CLEAR_DISABLED", TPM_E_BASE + 5, 35 | "The clear disable flag is set and all clear operations now require\n\ 36 | physical access" }, 37 | { "TPM_DEACTIVATED", TPM_E_BASE + 6, 38 | "The TPM is deactivated" }, 39 | { "TPM_DISABLED", TPM_E_BASE + 7, 40 | "The TPM is disabled" }, 41 | { "TPM_DISABLED_CMD", TPM_E_BASE + 8, 42 | "The target command has been disabled" }, 43 | { "TPM_FAIL", TPM_E_BASE + 9, 44 | "The operation failed" }, 45 | { "TPM_BAD_ORDINAL", TPM_E_BASE + 10, 46 | "The ordinal was unknown or inconsistent" }, 47 | { "TPM_INSTALL_DISABLED", TPM_E_BASE + 11, 48 | "The ability to install an owner is disabled" }, 49 | { "TPM_INVALID_KEYHANDLE", TPM_E_BASE + 12, 50 | "The key handle can not be interpreted" }, 51 | { "TPM_KEYNOTFOUND", TPM_E_BASE + 13, 52 | "The key handle points to an invalid key" }, 53 | { "TPM_INAPPROPRIATE_ENC", TPM_E_BASE + 14, 54 | "Unacceptable encryption scheme" }, 55 | { "TPM_MIGRATEFAIL", TPM_E_BASE + 15, 56 | "Migration authorization failed" }, 57 | { "TPM_INVALID_PCR_INFO", TPM_E_BASE + 16, 58 | "PCR information could not be interpreted" }, 59 | { "TPM_NOSPACE", TPM_E_BASE + 17, 60 | "No room to load key" }, 61 | { "TPM_NOSRK", TPM_E_BASE + 18, 62 | "There is no SRK set" }, 63 | { "TPM_NOTSEALED_BLOB", TPM_E_BASE + 19, 64 | "An encrypted blob is invalid or was not created by this TPM" }, 65 | { "TPM_OWNER_SET", TPM_E_BASE + 20, 66 | "There is already an Owner" }, 67 | { "TPM_RESOURCES", TPM_E_BASE + 21, 68 | "The TPM has insufficient internal resources to perform the requested action" }, 69 | { "TPM_SHORTRANDOM", TPM_E_BASE + 22, 70 | "A random string was too short" }, 71 | { "TPM_SIZE", TPM_E_BASE + 23, 72 | "The TPM does not have the space to perform the operation" }, 73 | { "TPM_WRONGPCRVAL", TPM_E_BASE + 24, 74 | "The named PCR value does not match the current PCR value" }, 75 | { "TPM_BAD_PARAM_SIZE", TPM_E_BASE + 25, 76 | "The paramSize argument to the command has the incorrect value" }, 77 | { "TPM_SHA_THREAD", TPM_E_BASE + 26, 78 | "There is no existing SHA-1 thread" }, 79 | { "TPM_SHA_ERROR", TPM_E_BASE + 27, 80 | "The calculation is unable to proceed because the existing SHA-1\n\ 81 | thread has already encountered an error" }, 82 | { "TPM_FAILEDSELFTEST", TPM_E_BASE + 28, 83 | "Self-test has failed and the TPM has shutdown" }, 84 | { "TPM_AUTH2FAIL", TPM_E_BASE + 29, 85 | "The authorization for the second key in a 2 key function\n\ 86 | failed authorization" }, 87 | { "TPM_BADTAG", TPM_E_BASE + 30, 88 | "The tag value sent to for a command is invalid" }, 89 | { "TPM_IOERROR", TPM_E_BASE + 31, 90 | "An IO error occurred transmitting information to the TPM" }, 91 | { "TPM_ENCRYPT_ERROR", TPM_E_BASE + 32, 92 | "The encryption process had a problem" }, 93 | { "TPM_DECRYPT_ERROR", TPM_E_BASE + 33, 94 | "The decryption process did not complete" }, 95 | { "TPM_INVALID_AUTHHANDLE", TPM_E_BASE + 34, 96 | "An invalid handle was used" }, 97 | { "TPM_NO_ENDORSEMENT", TPM_E_BASE + 35, 98 | "The TPM does not a EK installed" }, 99 | { "TPM_INVALID_KEYUSAGE", TPM_E_BASE + 36, 100 | "The usage of a key is not allowed" }, 101 | { "TPM_WRONG_ENTITYTYPE", TPM_E_BASE + 37, 102 | "The submitted entity type is not allowed" }, 103 | { "TPM_INVALID_POSTINIT", TPM_E_BASE + 38, 104 | "The command was received in the wrong sequence relative to TPM_Init\n\ 105 | and a subsequent TPM_Startup" }, 106 | { "TPM_INAPPROPRIATE_SIG", TPM_E_BASE + 39, 107 | "Signed data cannot include additional DER information" }, 108 | { "TPM_BAD_KEY_PROPERTY", TPM_E_BASE + 40, 109 | "The key properties in TPM_KEY_PARMs are not supported by this TPM" }, 110 | { "TPM_BAD_MIGRATION", TPM_E_BASE + 41, 111 | "The migration properties of this key are incorrect" }, 112 | { "TPM_BAD_SCHEME", TPM_E_BASE + 42, 113 | "The signature or encryption scheme for this key is incorrect or not\n\ 114 | permitted in this situation" }, 115 | { "TPM_BAD_DATASIZE", TPM_E_BASE + 43, 116 | "The size of the data (or blob) parameter is bad or inconsistent\n\ 117 | with the referenced key" }, 118 | { "TPM_BAD_MODE", TPM_E_BASE + 44, 119 | "A mode parameter is bad, such as capArea or subCapArea for\n\ 120 | TPM_GetCapability, physicalPresence parameter for TPM_PhysicalPresence,\n\ 121 | or migrationType for, TPM_CreateMigrationBlob" }, 122 | { "TPM_BAD_PRESENCE", TPM_E_BASE + 45, 123 | "Either the physicalPresence or physicalPresenceLock bits\n\ 124 | have the wrong value" }, 125 | { "TPM_BAD_VERSION", TPM_E_BASE + 46, 126 | "The TPM cannot perform this version of the capability" }, 127 | { "TPM_NO_WRAP_TRANSPORT", TPM_E_BASE + 47, 128 | "The TPM does not allow for wrapped transport sessions" }, 129 | { "TPM_AUDITFAIL_UNSUCCESSFUL", TPM_E_BASE + 48, 130 | "TPM audit construction failed and the underlying command\n\ 131 | was returning a failure code also" }, 132 | { "TPM_AUDITFAIL_SUCCESSFUL", TPM_E_BASE + 49, 133 | "TPM audit construction failed and the underlying command\n\ 134 | was returning success" }, 135 | { "TPM_NOTRESETABLE", TPM_E_BASE + 50, 136 | "Attempt to reset a PCR register that does not have the resettable attribute" }, 137 | { "TPM_NOTLOCAL", TPM_E_BASE + 51, 138 | "Attempt to reset a PCR register that requires locality\n\ 139 | and locality modifier not part of command transport" }, 140 | { "TPM_BAD_TYPE", TPM_E_BASE + 52, 141 | "Make identity blob not properly typed" }, 142 | { "TPM_INVALID_RESOURCE", TPM_E_BASE + 53, 143 | "When saving context identified resource type does not match actual resource" }, 144 | { "TPM_NOTFIPS", TPM_E_BASE + 54, 145 | "The TPM is attempting to execute a command only available when in FIPS mode" }, 146 | { "TPM_INVALID_FAMILY", TPM_E_BASE + 55, 147 | "The command is attempting to use an invalid family ID" }, 148 | { "TPM_NO_NV_PERMISSION", TPM_E_BASE + 56, 149 | "The permission to manipulate the NV storage is not available" }, 150 | { "TPM_REQUIRES_SIGN", TPM_E_BASE + 57, 151 | "The operation requires a signed command" }, 152 | { "TPM_KEY_NOTSUPPORTED", TPM_E_BASE + 58, 153 | "Wrong operation to load an NV key" }, 154 | { "TPM_AUTH_CONFLICT", TPM_E_BASE + 59, 155 | "NV_LoadKey blob requires both owner and blob authorization" }, 156 | { "TPM_AREA_LOCKED", TPM_E_BASE + 60, 157 | "The NV area is locked and not writable" }, 158 | { "TPM_BAD_LOCALITY", TPM_E_BASE + 61, 159 | "The locality is incorrect for the attempted operation" }, 160 | { "TPM_READ_ONLY", TPM_E_BASE + 62, 161 | "The NV area is read only and canât be written to" }, 162 | { "TPM_PER_NOWRITE", TPM_E_BASE + 63, 163 | "There is no protection on the write to the NV area" }, 164 | { "TPM_FAMILYCOUNT", TPM_E_BASE + 64, 165 | "The family count value does not match" }, 166 | { "TPM_WRITE_LOCKED", TPM_E_BASE + 65, 167 | "The NV area has already been written to" }, 168 | { "TPM_BAD_ATTRIBUTES", TPM_E_BASE + 66, 169 | "The NV area attributes conflict" }, 170 | { "TPM_INVALID_STRUCTURE", TPM_E_BASE + 67, 171 | "The structure tag and version are invalid or inconsistent" }, 172 | { "TPM_KEY_OWNER_CONTROL", TPM_E_BASE + 68, 173 | "The key is under control of the TPM Owner and can only be evicted\n\ 174 | by the TPM Owner" }, 175 | { "TPM_BAD_COUNTER", TPM_E_BASE + 69, 176 | "The counter handle is incorrect" }, 177 | { "TPM_NOT_FULLWRITE", TPM_E_BASE + 70, 178 | "The write is not a complete write of the area" }, 179 | { "TPM_CONTEXT_GAP", TPM_E_BASE + 71, 180 | "The gap between saved context counts is too large" }, 181 | { "TPM_MAXNVWRITES", TPM_E_BASE + 72, 182 | "The maximum number of NV writes without an owner has been exceeded" }, 183 | { "TPM_NOOPERATOR", TPM_E_BASE + 73, 184 | "No operator AuthData value is set" }, 185 | { "TPM_RESOURCEMISSING", TPM_E_BASE + 74, 186 | "The resource pointed to by context is not loaded" }, 187 | { "TPM_DELEGATE_LOCK", TPM_E_BASE + 75, 188 | "The delegate administration is locked" }, 189 | { "TPM_DELEGATE_FAMILY", TPM_E_BASE + 76, 190 | "Attempt to manage a family other then the delegated family" }, 191 | { "TPM_DELEGATE_ADMIN", TPM_E_BASE + 77, 192 | "Delegation table management not enabled" }, 193 | { "TPM_TRANSPORT_NOTEXCLUSIVE", TPM_E_BASE + 78, 194 | "There was a command executed outside of an exclusive transport session" }, 195 | { "TPM_OWNER_CONTROL", TPM_E_BASE + 79, 196 | "Attempt to context save a owner evict controlled key" }, 197 | { "TPM_DAA_RESOURCES", TPM_E_BASE + 80, 198 | "The DAA command has no resources available to execute the command" }, 199 | { "TPM_DAA_INPUT_DATA0", TPM_E_BASE + 81, 200 | "The consistency check on DAA parameter inputData0 has failed" }, 201 | { "TPM_DAA_INPUT_DATA1", TPM_E_BASE + 82, 202 | "The consistency check on DAA parameter inputData1 has failed" }, 203 | { "TPM_DAA_ISSUER_SETTINGS", TPM_E_BASE + 83, 204 | "The consistency check on DAA_issuerSettings has failed" }, 205 | { "TPM_DAA_TPM_SETTINGS", TPM_E_BASE + 84, 206 | "The consistency check on DAA_tpmSpecific has failed" }, 207 | { "TPM_DAA_STAGE", TPM_E_BASE + 85, 208 | "The atomic process indicated by the submitted DAA command is not\n\ 209 | the expected process" }, 210 | { "TPM_DAA_ISSUER_VALIDITY", TPM_E_BASE + 86, 211 | "The issuerâs validity check has detected an inconsistency" }, 212 | { "TPM_DAA_WRONG_W", TPM_E_BASE + 87, 213 | "The consistency check on w has failed" }, 214 | { "TPM_BAD_HANDLE", TPM_E_BASE + 88, 215 | "The handle is incorrect" }, 216 | { "TPM_BAD_DELEGATE", TPM_E_BASE + 89, 217 | "Delegation is not correct" }, 218 | { "TPM_BADCONTEXT", TPM_E_BASE + 90, 219 | "The context blob is invalid" }, 220 | { "TPM_TOOMANYCONTEXTS", TPM_E_BASE + 91, 221 | "Too many contexts held by the TPM" }, 222 | { "TPM_MA_TICKET_SIGNATURE", TPM_E_BASE + 92, 223 | "Migration authority signature validation failure" }, 224 | { "TPM_MA_DESTINATION", TPM_E_BASE + 93, 225 | "Migration destination not authenticated" }, 226 | { "TPM_MA_SOURCE", TPM_E_BASE + 94, 227 | "Migration source incorrect" }, 228 | { "TPM_MA_AUTHORITY", TPM_E_BASE + 95, 229 | "Incorrect migration authority" }, 230 | { "TPM_PERMANENTEK", TPM_E_BASE + 97, 231 | "Attempt to revoke the EK and the EK is not revocable" }, 232 | { "TPM_BAD_SIGNATURE", TPM_E_BASE + 98, 233 | "Bad signature of CMK ticket" }, 234 | { "TPM_NOCONTEXTSPACE", TPM_E_BASE + 99, 235 | "There is no room in the context list for additional contexts" }, 236 | { "TPM_RETRY", TPM_E_BASE + TPM_E_NON_FATAL, 237 | "The TPM is too busy to respond to the command immediately, but\n\ 238 | the command could be resubmitted at a later time. The TPM MAY\n\ 239 | return TPM_RETRY for any command at any time" }, 240 | { "TPM_NEEDS_SELFTEST", TPM_E_BASE + TPM_E_NON_FATAL + 1, 241 | "TPM_ContinueSelfTest has not been run" }, 242 | { "TPM_DOING_SELFTEST", TPM_E_BASE + TPM_E_NON_FATAL + 2, 243 | "The TPM is currently executing the actions of TPM_ContinueSelfTest\n\ 244 | because the ordinal required resources that have not been tested" }, 245 | { "TPM_DEFEND_LOCK_RUNNING", TPM_E_BASE + TPM_E_NON_FATAL + 3, 246 | "The TPM is defending against dictionary attacks and is in some\n\ 247 | time-out period" }, 248 | }; 249 | 250 | #endif /* TPM_ERROR_MESSAGES_H */ 251 | -------------------------------------------------------------------------------- /patches/uboot-Makefile.patch: -------------------------------------------------------------------------------- 1 | diff --git a/Makefile b/Makefile 2 | index 328347d..1913503 100644 3 | --- a/Makefile 4 | +++ b/Makefile 5 | @@ -312,7 +312,9 @@ LIBS-y += arch/powerpc/cpu/mpc8xxx/lib8xxx.o 6 | endif 7 | LIBS-y += drivers/rtc/librtc.o 8 | LIBS-y += drivers/serial/libserial.o 9 | -LIBS-$(CONFIG_GENERIC_LPC_TPM) += drivers/tpm/libtpm.o 10 | +LIBS-$(CONFIG_TPM) += drivers/tpm/libtpm.o 11 | +LIBS-$(CONFIG_TPM) += lib/tlcl/libtlcl.o 12 | +LIBS-$(CONFIG_SBOOT) += lib/sboot/libsboot.o 13 | LIBS-y += drivers/twserial/libtws.o 14 | LIBS-y += drivers/usb/eth/libusb_eth.o 15 | LIBS-y += drivers/usb/gadget/libusb_gadget.o 16 | @@ -543,7 +545,8 @@ GEN_UBOOT = \ 17 | endif 18 | 19 | $(obj)u-boot: depend \ 20 | - $(SUBDIR_TOOLS) $(OBJS) $(LIBBOARD) $(LIBS) $(LDSCRIPT) $(obj)u-boot.lds 21 | + $(SUBDIR_TOOLS) $(OBJS) $(LIBBOARD) $(LIBS) $(LDSCRIPT) \ 22 | + $(VBOOT_TARGET) $(obj)u-boot.lds 23 | $(GEN_UBOOT) 24 | ifeq ($(CONFIG_KALLSYMS),y) 25 | smap=`$(call SYSTEM_MAP,$(obj)u-boot) | \ 26 | -------------------------------------------------------------------------------- /patches/uboot-common-Makefile.patch: -------------------------------------------------------------------------------- 1 | diff --git a/common/Makefile b/common/Makefile 2 | index eac6360..e3a38dd 100644 3 | --- a/common/Makefile 4 | +++ b/common/Makefile 5 | @@ -159,6 +159,8 @@ COBJS-$(CONFIG_CMD_TERMINAL) += cmd_terminal.o 6 | COBJS-$(CONFIG_CMD_TIME) += cmd_time.o 7 | COBJS-$(CONFIG_SYS_HUSH_PARSER) += cmd_test.o 8 | COBJS-$(CONFIG_CMD_TPM) += cmd_tpm.o 9 | +COBJS-$(CONFIG_CMD_TPM_TLCL) += cmd_tpm_tlcl.o 10 | +COBJS-$(CONFIG_CMD_SBOOT) += cmd_sboot.o 11 | COBJS-$(CONFIG_CMD_TSI148) += cmd_tsi148.o 12 | COBJS-$(CONFIG_CMD_UBI) += cmd_ubi.o 13 | COBJS-$(CONFIG_CMD_UBIFS) += cmd_ubifs.o 14 | -------------------------------------------------------------------------------- /patches/uboot-common-cmd_bootm.c.patch: -------------------------------------------------------------------------------- 1 | diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c 2 | index 83fa5d7..3fdecb8 100644 3 | --- a/common/cmd_bootm.c 4 | +++ b/common/cmd_bootm.c 5 | @@ -62,6 +62,10 @@ 6 | #include 7 | #endif /* CONFIG_LZO */ 8 | 9 | +#ifdef CONFIG_SBOOT 10 | +#include 11 | +#endif 12 | + 13 | DECLARE_GLOBAL_DATA_PTR; 14 | 15 | #ifndef CONFIG_SYS_BOOTM_LEN 16 | @@ -190,6 +194,37 @@ static void boot_start_lmb(bootm_headers_t *images) 17 | static inline void boot_start_lmb(bootm_headers_t *images) { } 18 | #endif 19 | 20 | +#ifdef CONFIG_SBOOT 21 | +void bootm_sboot(void) 22 | +{ 23 | + printf("Sboot measuring ... "); 24 | + 25 | + /* Measure loaded images (kernel, ramdisk, fdt) */ 26 | + sboot_extend_os(images.os.image_start, images.os.image_len); 27 | + sboot_extend_os(images.rd_start, images.rd_end - images.rd_start); 28 | + sboot_extend_os(images.initrd_start, images.initrd_end - images.initrd_start); 29 | + sboot_extend_os(images.cmdline_start, images.cmdline_end - images.initrd_start); 30 | +#ifdef CONFIG_OF_LIBFDT 31 | + sboot_extend_os(images.ft_addr, images.ft_len); 32 | +#endif 33 | + 34 | + /* If the SBOOT seal command was issued, bootm should now seal state. */ 35 | + if (getenv("sbootseal") != NULL) { 36 | + sboot_seal_os(); 37 | + } 38 | + 39 | + /* Verify (default=enable) sealed blob. */ 40 | + if (sboot_check_os() != SBOOT_SUCCESS) { 41 | + /* If CONFIG_SBOOT_ENFORCE is enabled the system is already hung. */ 42 | + puts("Failed\n"); 43 | + } else { 44 | + puts("OK\n"); 45 | + } 46 | + 47 | + sboot_finish(); 48 | +} 49 | +#endif 50 | + 51 | static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 52 | { 53 | void *os_hdr; 54 | @@ -571,6 +606,9 @@ int do_bootm_subcommand(cmd_tbl_t *cmdtp, int flag, int argc, 55 | */ 56 | eth_halt(); 57 | #endif 58 | +#ifdef CONFIG_SBOOT 59 | + bootm_sboot(); 60 | +#endif 61 | arch_preboot_os(); 62 | boot_fn(BOOTM_STATE_OS_GO, argc, argv, &images); 63 | break; 64 | @@ -647,6 +685,10 @@ int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 65 | usb_stop(); 66 | #endif 67 | 68 | +#ifdef CONFIG_SBOOT 69 | + bootm_sboot(); 70 | +#endif 71 | + 72 | ret = bootm_load_os(images.os, &load_end, 1); 73 | 74 | if (ret < 0) { 75 | @@ -1629,6 +1671,10 @@ static int do_bootz(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 76 | usb_stop(); 77 | #endif 78 | 79 | +#ifdef CONFIG_SBOOT 80 | + bootm_sboot(); 81 | +#endif 82 | + 83 | #ifdef CONFIG_SILENT_CONSOLE 84 | fixup_silent_linux(); 85 | #endif 86 | -------------------------------------------------------------------------------- /patches/uboot-common-env_common.c.patch: -------------------------------------------------------------------------------- 1 | diff --git a/common/env_common.c b/common/env_common.c 2 | index 3d3cb70..d498344 100644 3 | --- a/common/env_common.c 4 | +++ b/common/env_common.c 5 | @@ -143,6 +143,10 @@ int env_import(const char *buf, int check) 6 | { 7 | env_t *ep = (env_t *)buf; 8 | 9 | +#if defined(CONFIG_SBOOT) && !defined(CONFIG_SBOOT_DISABLE_ENV_EXTEND) 10 | + sboot_extend_environment(buf, CONFIG_ENV_SIZE); 11 | +#endif 12 | + 13 | if (check) { 14 | uint32_t crc; 15 | 16 | -------------------------------------------------------------------------------- /patches/uboot-common-main.c.patch: -------------------------------------------------------------------------------- 1 | diff --git a/common/main.c b/common/main.c 2 | index 9507cec..bb797e3 100644 3 | --- a/common/main.c 4 | +++ b/common/main.c 5 | @@ -917,13 +917,23 @@ static int cread_line(const char *const prompt, char *buf, unsigned int *len, 6 | */ 7 | int readline (const char *const prompt) 8 | { 9 | + int result; 10 | /* 11 | * If console_buffer isn't 0-length the user will be prompted to modify 12 | * it instead of entering it from scratch as desired. 13 | */ 14 | console_buffer[0] = '\0'; 15 | 16 | - return readline_into_buffer(prompt, console_buffer, 0); 17 | + result = readline_into_buffer(prompt, console_buffer, 0); 18 | + 19 | +#if defined(CONFIG_SBOOT) && !defined(CONFIG_SBOOT_DISABLE_CONSOLE_EXTEND) 20 | + /* Must extend console PCR whether or not command was interpreted 21 | + * or successful. If not, executable code may be introduced using 22 | + * the console history buffer. 23 | + */ 24 | + sboot_extend_console(console_buffer, CONFIG_SYS_CBSIZE); 25 | +#endif 26 | + return result; 27 | } 28 | 29 | 30 | @@ -1365,6 +1375,14 @@ static int builtin_run_command(const char *cmd, int flag) 31 | */ 32 | int run_command(const char *cmd, int flag) 33 | { 34 | +#if defined(CONFIG_SBOOT) && !defined(CONFIG_SBOOT_DISABLE_CONSOLE_EXTEND) 35 | + /* Must extend console PCR whether or not command was interpreted 36 | + * or successful. If not, executable code may be introduced using 37 | + * the console history buffer. 38 | + */ 39 | + sboot_extend_console(cmd, strlen(cmd)); 40 | +#endif 41 | + 42 | #ifndef CONFIG_SYS_HUSH_PARSER 43 | /* 44 | * builtin_run_command can return 0 or 1 for success, so clean up 45 | @@ -1439,6 +1457,15 @@ int run_command_list(const char *cmd, int len, int flag) 46 | need_buff = strchr(cmd, '\n') != NULL; 47 | #endif 48 | } 49 | + 50 | +#if defined(CONFIG_SBOOT) && !defined(CONFIG_SBOOT_DISABLE_CONSOLE_EXTEND) 51 | + /* Must extend console PCR whether or not command was interpreted 52 | + * or successful. If not, executable code may be introduced using 53 | + * the console history buffer. 54 | + */ 55 | + sboot_extend_console(cmd, len); 56 | +#endif 57 | + 58 | if (need_buff) { 59 | buff = malloc(len + 1); 60 | if (!buff) 61 | -------------------------------------------------------------------------------- /patches/uboot-common-spl-spl.c.patch: -------------------------------------------------------------------------------- 1 | diff --git a/common/spl/spl.c b/common/spl/spl.c 2 | index 0d829c0..0a4d799 100644 3 | --- a/common/spl/spl.c 4 | +++ b/common/spl/spl.c 5 | @@ -31,6 +31,7 @@ 6 | #include 7 | #include 8 | #include 9 | +#include 10 | #include 11 | 12 | DECLARE_GLOBAL_DATA_PTR; 13 | @@ -59,7 +60,7 @@ inline void hang(void) 14 | * Default function to determine if u-boot or the OS should 15 | * be started. This implementation always returns 1. 16 | * 17 | - * Please implement your own board specific funcion to do this. 18 | + * Please implement your own board specific function to do this. 19 | * 20 | * RETURN 21 | * 0 to not start u-boot 22 | @@ -210,6 +211,20 @@ void board_init_r(gd_t *dummy1, ulong dummy2) 23 | hang(); 24 | } 25 | 26 | +#ifdef CONFIG_SPL_SBOOT_SUPPORT 27 | +#if !defined(CONFIG_SPL_MMC_SD_FAT_BOOT_DEVICE) || CONFIG_SPL_MMC_SD_FAT_BOOT_DEVICE == 0 28 | +#warning "CONFIG_SPL_MMC_SD_FAT_BOOT_DEVICE may not be configured or may \ 29 | + configured as the same device as the SPL image. If implementing a trusted \ 30 | + or secured boot (with SBOOT) your SRTM (SPL) should be read from write \ 31 | + protected storage." 32 | +#endif 33 | + sboot_init(); 34 | + spl_sboot_extend(); 35 | + 36 | + /* Assumes IH_OS_U_BOOT */ 37 | + spl_sboot_check(); 38 | +#endif 39 | + 40 | switch (spl_image.os) { 41 | case IH_OS_U_BOOT: 42 | debug("Jumping to U-Boot\n"); 43 | -------------------------------------------------------------------------------- /patches/uboot-drivers-mmc-spl_mmc.c.patch: -------------------------------------------------------------------------------- 1 | diff --git a/drivers/mmc/spl_mmc.c b/drivers/mmc/spl_mmc.c 2 | index 753c6a0..af4cf4e 100644 3 | --- a/drivers/mmc/spl_mmc.c 4 | +++ b/drivers/mmc/spl_mmc.c 5 | @@ -108,8 +108,13 @@ void spl_mmc_load_image(void) 6 | u32 boot_mode; 7 | 8 | mmc_initialize(gd->bd); 9 | - /* We register only one device. So, the dev id is always 0 */ 10 | + /* Boards may register multiple devices (e.g., OMAP3) */ 11 | +#ifdef CONFIG_SPL_MMC_SD_FAT_BOOT_DEVICE 12 | + mmc = find_mmc_device(CONFIG_SPL_MMC_SD_FAT_BOOT_DEVICE); 13 | +#else 14 | + /* We 'may' register only one device. So, the dev id is always 0 */ 15 | mmc = find_mmc_device(0); 16 | +#endif 17 | if (!mmc) { 18 | puts("spl: mmc device not found!!\n"); 19 | hang(); 20 | -------------------------------------------------------------------------------- /patches/uboot-include-sha1.h.patch: -------------------------------------------------------------------------------- 1 | diff --git a/include/sha1.h b/include/sha1.h 2 | index 734d1fb..6ad159d 100644 3 | --- a/include/sha1.h 4 | +++ b/include/sha1.h 5 | @@ -45,6 +45,8 @@ typedef struct 6 | } 7 | sha1_context; 8 | 9 | +typedef sha1_context SHA1_CTX; 10 | + 11 | /** 12 | * \brief SHA-1 context setup 13 | * 14 | @@ -59,7 +61,7 @@ void sha1_starts( sha1_context *ctx ); 15 | * \param input buffer holding the data 16 | * \param ilen length of the input data 17 | */ 18 | -void sha1_update( sha1_context *ctx, unsigned char *input, int ilen ); 19 | +void sha1_update( sha1_context *ctx, const unsigned char *input, int ilen ); 20 | 21 | /** 22 | * \brief SHA-1 final digest 23 | @@ -76,7 +78,7 @@ void sha1_finish( sha1_context *ctx, unsigned char output[20] ); 24 | * \param ilen length of the input data 25 | * \param output SHA-1 checksum result 26 | */ 27 | -void sha1_csum( unsigned char *input, int ilen, 28 | +void sha1_csum( const unsigned char *input, int ilen, 29 | unsigned char output[20] ); 30 | 31 | /** 32 | @@ -87,7 +89,7 @@ void sha1_csum( unsigned char *input, int ilen, 33 | * \param output SHA-1 checksum result 34 | * \param chunk_sz watchdog triggering period (in bytes of input processed) 35 | */ 36 | -void sha1_csum_wd (unsigned char *input, int ilen, 37 | +void sha1_csum_wd (const unsigned char *input, int ilen, 38 | unsigned char output[20], unsigned int chunk_sz); 39 | 40 | /** 41 | @@ -108,10 +110,14 @@ int sha1_file( char *path, unsigned char output[20] ); 42 | * \param ilen length of the input data 43 | * \param output HMAC-SHA-1 result 44 | */ 45 | -void sha1_hmac( unsigned char *key, int keylen, 46 | - unsigned char *input, int ilen, 47 | +void sha1_hmac( const unsigned char *key, int keylen, 48 | + const unsigned char *input, int ilen, 49 | unsigned char output[20] ); 50 | 51 | +void hmac_starts( sha1_context *ctx, const unsigned char *key, unsigned int len); 52 | +void hmac_update( sha1_context *ctx, const unsigned char *data, unsigned int len); 53 | +void hmac_finish( sha1_context *ctx, const unsigned char *key, unsigned int len, unsigned char *output); 54 | + 55 | /** 56 | * \brief Checkup routine 57 | * 58 | -------------------------------------------------------------------------------- /patches/uboot-lib-Makefile.patch: -------------------------------------------------------------------------------- 1 | diff --git a/lib/Makefile b/lib/Makefile 2 | index e44e045..67a1e76 100644 3 | --- a/lib/Makefile 4 | +++ b/lib/Makefile 5 | @@ -49,13 +49,16 @@ COBJS-y += ldiv.o 6 | COBJS-$(CONFIG_MD5) += md5.o 7 | COBJS-y += net_utils.o 8 | COBJS-y += qsort.o 9 | -COBJS-$(CONFIG_SHA1) += sha1.o 10 | +ifneq ($(CONFIG_TPM)$(CONFIG_SHA1),) 11 | +COBJS-y += sha1.o 12 | +endif 13 | COBJS-$(CONFIG_SHA256) += sha256.o 14 | COBJS-y += strmhz.o 15 | COBJS-$(CONFIG_RBTREE) += rbtree.o 16 | endif 17 | 18 | ifdef CONFIG_SPL_BUILD 19 | +COBJS-$(CONFIG_SPL_TPM_SUPPORT) += sha1.o 20 | COBJS-$(CONFIG_SPL_YMODEM_SUPPORT) += crc16.o 21 | COBJS-$(CONFIG_SPL_NET_SUPPORT) += crc32.o 22 | ifneq ($(CONFIG_SPL_SPI_FLASH_SUPPORT)$(CONFIG_SPL_NET_SUPPORT),) 23 | -------------------------------------------------------------------------------- /patches/uboot-lib-sha1.c.patch: -------------------------------------------------------------------------------- 1 | diff --git a/lib/sha1.c b/lib/sha1.c 2 | index da5bc16..edfd6fd 100644 3 | --- a/lib/sha1.c 4 | +++ b/lib/sha1.c 5 | @@ -36,7 +36,7 @@ 6 | #include 7 | #endif /* USE_HOSTCC */ 8 | #include 9 | -#include "sha1.h" 10 | +#include 11 | 12 | /* 13 | * 32-bit integer manipulation macros (big endian) 14 | @@ -73,7 +73,7 @@ void sha1_starts (sha1_context * ctx) 15 | ctx->state[4] = 0xC3D2E1F0; 16 | } 17 | 18 | -static void sha1_process (sha1_context * ctx, unsigned char data[64]) 19 | +static void sha1_process (sha1_context * ctx, const unsigned char data[64]) 20 | { 21 | unsigned long temp, W[16], A, B, C, D, E; 22 | 23 | @@ -230,7 +230,7 @@ static void sha1_process (sha1_context * ctx, unsigned char data[64]) 24 | /* 25 | * SHA-1 process buffer 26 | */ 27 | -void sha1_update (sha1_context * ctx, unsigned char *input, int ilen) 28 | +void sha1_update (sha1_context * ctx, const unsigned char *input, int ilen) 29 | { 30 | int fill; 31 | unsigned long left; 32 | @@ -305,7 +305,7 @@ void sha1_finish (sha1_context * ctx, unsigned char output[20]) 33 | /* 34 | * Output = SHA-1( input buffer ) 35 | */ 36 | -void sha1_csum (unsigned char *input, int ilen, unsigned char output[20]) 37 | +void sha1_csum (const unsigned char *input, int ilen, unsigned char output[20]) 38 | { 39 | sha1_context ctx; 40 | 41 | @@ -318,7 +318,7 @@ void sha1_csum (unsigned char *input, int ilen, unsigned char output[20]) 42 | * Output = SHA-1( input buffer ). Trigger the watchdog every 'chunk_sz' 43 | * bytes of input processed. 44 | */ 45 | -void sha1_csum_wd (unsigned char *input, int ilen, unsigned char output[20], 46 | +void sha1_csum_wd (const unsigned char *input, int ilen, unsigned char output[20], 47 | unsigned int chunk_sz) 48 | { 49 | sha1_context ctx; 50 | @@ -347,11 +347,56 @@ void sha1_csum_wd (unsigned char *input, int ilen, unsigned char output[20], 51 | sha1_finish (&ctx, output); 52 | } 53 | 54 | +void hmac_starts(sha1_context *ctx, const unsigned char *key, unsigned int len) 55 | +{ 56 | + unsigned short i; 57 | + unsigned char k_ipad[64]; 58 | + 59 | + memset(k_ipad, 0x36, 64); 60 | + sha1_starts(ctx); 61 | + 62 | + for (i = 0; i < len; ++i) { 63 | + if (i >= 64) break; 64 | + k_ipad[i] ^= key[i]; 65 | + } 66 | + 67 | + sha1_update(ctx, k_ipad, 64); 68 | + memset(k_ipad, 0, 64); 69 | +} 70 | + 71 | +void hmac_update(sha1_context *ctx, const unsigned char *data, unsigned int len) 72 | +{ 73 | + sha1_update(ctx, data, len); 74 | +} 75 | + 76 | +void hmac_finish(sha1_context *ctx, const unsigned char *key, unsigned int len, unsigned char *output) 77 | +{ 78 | + unsigned short i; 79 | + unsigned char k_opad[64], dest[20]; 80 | + 81 | + memset(k_opad, 0x5C, 64); 82 | + sha1_finish(ctx, dest); 83 | + 84 | + for (i = 0; i < len; ++i) { 85 | + if (i >= 64) break; 86 | + k_opad[i] ^= key[i]; 87 | + } 88 | + 89 | + sha1_starts(ctx); 90 | + sha1_update(ctx, k_opad, 64); 91 | + sha1_update(ctx, dest, 20); 92 | + sha1_finish(ctx, output); 93 | + 94 | + memset(dest, 0, 20); 95 | + memset(k_opad, 0, 64); 96 | + memset(ctx, 0, sizeof(sha1_context)); 97 | +} 98 | + 99 | /* 100 | * Output = HMAC-SHA-1( input buffer, hmac key ) 101 | */ 102 | -void sha1_hmac (unsigned char *key, int keylen, 103 | - unsigned char *input, int ilen, unsigned char output[20]) 104 | +void sha1_hmac (const unsigned char *key, int keylen, 105 | + const unsigned char *input, int ilen, unsigned char output[20]) 106 | { 107 | int i; 108 | sha1_context ctx; 109 | -------------------------------------------------------------------------------- /patches/uboot-spl-Makefile.patch: -------------------------------------------------------------------------------- 1 | diff --git a/spl/Makefile b/spl/Makefile 2 | index 20a943c..eaf23f9 100644 3 | --- a/spl/Makefile 4 | +++ b/spl/Makefile 5 | @@ -61,6 +61,11 @@ LIBS-$(CONFIG_SPL_NET_SUPPORT) += net/libnet.o 6 | LIBS-$(CONFIG_SPL_ETH_SUPPORT) += drivers/net/libnet.o 7 | LIBS-$(CONFIG_SPL_ETH_SUPPORT) += drivers/net/phy/libphy.o 8 | 9 | +# TPM, tlcl, and sboot 10 | +LIBS-$(CONFIG_SPL_TPM_SUPPORT) += drivers/tpm/libtpm.o 11 | +LIBS-$(CONFIG_SPL_TPM_SUPPORT) += lib/tlcl/libtlcl.o 12 | +LIBS-$(CONFIG_SPL_SBOOT_SUPPORT) += lib/sboot/libsboot.o 13 | + 14 | ifneq ($(CONFIG_AM33XX)$(CONFIG_OMAP34XX)$(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX),) 15 | LIBS-y += $(CPUDIR)/omap-common/libomap-common.o 16 | endif 17 | --------------------------------------------------------------------------------