OLD | NEW |
(Empty) | |
| 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 /* 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 "sysincludes.h" |
| 18 #include "tlcl.h" |
| 19 #include "tlcl_internal.h" |
| 20 #include "tlcl_structures.h" |
| 21 #include "tss_constants.h" |
| 22 #include "utility.h" |
| 23 |
| 24 |
| 25 /* Sets the size field of a TPM command. */ |
| 26 static INLINE void SetTpmCommandSize(uint8_t* buffer, uint32_t size) { |
| 27 ToTpmUint32(buffer + sizeof(uint16_t), size); |
| 28 } |
| 29 |
| 30 /* Gets the size field of a TPM command. */ |
| 31 POSSIBLY_UNUSED static INLINE int TpmCommandSize(const uint8_t* buffer) { |
| 32 uint32_t size; |
| 33 FromTpmUint32(buffer + sizeof(uint16_t), &size); |
| 34 return (int) size; |
| 35 } |
| 36 |
| 37 /* Gets the code field of a TPM command. */ |
| 38 static INLINE int TpmCommandCode(const uint8_t* buffer) { |
| 39 uint32_t code; |
| 40 FromTpmUint32(buffer + sizeof(uint16_t) + sizeof(uint32_t), &code); |
| 41 return code; |
| 42 } |
| 43 |
| 44 /* Gets the return code field of a TPM result. */ |
| 45 static INLINE int TpmReturnCode(const uint8_t* buffer) { |
| 46 return TpmCommandCode(buffer); |
| 47 } |
| 48 |
| 49 /* Checks for errors in a TPM response. */ |
| 50 static void CheckResult(uint8_t* request, uint8_t* response, int warn_only) { |
| 51 int command = TpmCommandCode(request); |
| 52 int result = TpmReturnCode(response); |
| 53 if (result != TPM_SUCCESS) { |
| 54 if (warn_only) |
| 55 VBDEBUG(("TPM command %d 0x%x failed: %d 0x%x\n", |
| 56 command, command, result, result)); |
| 57 else |
| 58 error("TPM command %d 0x%x failed: %d 0x%x\n", |
| 59 command, command, result, result); |
| 60 } |
| 61 } |
| 62 |
| 63 /* Sends a TPM command and gets a response. */ |
| 64 static void TlclSendReceive(uint8_t* request, uint8_t* response, |
| 65 int max_length) { |
| 66 TlclStubSendReceive(request, TpmCommandSize(request), |
| 67 response, max_length); |
| 68 } |
| 69 |
| 70 |
| 71 /* Sends a command and returns the error code. */ |
| 72 static uint32_t Send(uint8_t* command) { |
| 73 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; |
| 74 TlclSendReceive(command, response, sizeof(response)); |
| 75 return TpmReturnCode(response); |
| 76 } |
| 77 |
| 78 /* Exported functions. */ |
| 79 |
| 80 void TlclLibInit(void) { |
| 81 TlclStubInit(); |
| 82 } |
| 83 |
| 84 uint32_t TlclStartup(void) { |
| 85 return Send(tpm_startup_cmd.buffer); |
| 86 } |
| 87 |
| 88 uint32_t TlclSelftestfull(void) { |
| 89 return Send(tpm_selftestfull_cmd.buffer); |
| 90 } |
| 91 |
| 92 uint32_t TlclContinueSelfTest(void) { |
| 93 return Send(tpm_continueselftest_cmd.buffer); |
| 94 } |
| 95 |
| 96 uint32_t TlclDefineSpace(uint32_t index, uint32_t perm, uint32_t size) { |
| 97 ToTpmUint32(tpm_nv_definespace_cmd.index, index); |
| 98 ToTpmUint32(tpm_nv_definespace_cmd.perm, perm); |
| 99 ToTpmUint32(tpm_nv_definespace_cmd.size, size); |
| 100 return Send(tpm_nv_definespace_cmd.buffer); |
| 101 } |
| 102 |
| 103 uint32_t TlclWrite(uint32_t index, uint8_t* data, uint32_t length) { |
| 104 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; |
| 105 const int total_length = |
| 106 kTpmRequestHeaderLength + kWriteInfoLength + length; |
| 107 |
| 108 assert(total_length <= TPM_LARGE_ENOUGH_COMMAND_SIZE); |
| 109 SetTpmCommandSize(tpm_nv_write_cmd.buffer, total_length); |
| 110 |
| 111 ToTpmUint32(tpm_nv_write_cmd.index, index); |
| 112 ToTpmUint32(tpm_nv_write_cmd.length, length); |
| 113 Memcpy(tpm_nv_write_cmd.data, data, length); |
| 114 |
| 115 TlclSendReceive(tpm_nv_write_cmd.buffer, response, sizeof(response)); |
| 116 CheckResult(tpm_nv_write_cmd.buffer, response, 1); |
| 117 |
| 118 return TpmReturnCode(response); |
| 119 } |
| 120 |
| 121 uint32_t TlclRead(uint32_t index, uint8_t* data, uint32_t length) { |
| 122 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; |
| 123 uint32_t result_length; |
| 124 uint32_t result; |
| 125 |
| 126 ToTpmUint32(tpm_nv_read_cmd.index, index); |
| 127 ToTpmUint32(tpm_nv_read_cmd.length, length); |
| 128 |
| 129 TlclSendReceive(tpm_nv_read_cmd.buffer, response, sizeof(response)); |
| 130 result = TpmReturnCode(response); |
| 131 if (result == TPM_SUCCESS && length > 0) { |
| 132 uint8_t* nv_read_cursor = response + kTpmResponseHeaderLength; |
| 133 FromTpmUint32(nv_read_cursor, &result_length); |
| 134 nv_read_cursor += sizeof(uint32_t); |
| 135 Memcpy(data, nv_read_cursor, result_length); |
| 136 } |
| 137 |
| 138 return result; |
| 139 } |
| 140 |
| 141 uint32_t TlclWriteLock(uint32_t index) { |
| 142 return TlclWrite(index, NULL, 0); |
| 143 } |
| 144 |
| 145 uint32_t TlclReadLock(uint32_t index) { |
| 146 return TlclRead(index, NULL, 0); |
| 147 } |
| 148 |
| 149 uint32_t TlclAssertPhysicalPresence(void) { |
| 150 return Send(tpm_ppassert_cmd.buffer); |
| 151 } |
| 152 |
| 153 uint32_t TlclAssertPhysicalPresenceResult(void) { |
| 154 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; |
| 155 TlclSendReceive(tpm_ppassert_cmd.buffer, response, sizeof(response)); |
| 156 return TpmReturnCode(response); |
| 157 } |
| 158 |
| 159 uint32_t TlclLockPhysicalPresence(void) { |
| 160 return Send(tpm_pplock_cmd.buffer); |
| 161 } |
| 162 |
| 163 uint32_t TlclSetNvLocked(void) { |
| 164 return TlclDefineSpace(TPM_NV_INDEX_LOCK, 0, 0); |
| 165 } |
| 166 |
| 167 int TlclIsOwned(void) { |
| 168 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE + TPM_PUBEK_SIZE]; |
| 169 uint32_t result; |
| 170 TlclSendReceive(tpm_readpubek_cmd.buffer, response, sizeof(response)); |
| 171 result = TpmReturnCode(response); |
| 172 return (result != TPM_SUCCESS); |
| 173 } |
| 174 |
| 175 uint32_t TlclForceClear(void) { |
| 176 return Send(tpm_forceclear_cmd.buffer); |
| 177 } |
| 178 |
| 179 uint32_t TlclSetEnable(void) { |
| 180 return Send(tpm_physicalenable_cmd.buffer); |
| 181 } |
| 182 |
| 183 uint32_t TlclClearEnable(void) { |
| 184 return Send(tpm_physicaldisable_cmd.buffer); |
| 185 } |
| 186 |
| 187 uint32_t TlclSetDeactivated(uint8_t flag) { |
| 188 *((uint8_t*)tpm_physicalsetdeactivated_cmd.deactivated) = flag; |
| 189 return Send(tpm_physicalsetdeactivated_cmd.buffer); |
| 190 } |
| 191 |
| 192 uint32_t TlclGetFlags(uint8_t* disable, uint8_t* deactivated) { |
| 193 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; |
| 194 TPM_PERMANENT_FLAGS* pflags; |
| 195 uint32_t result; |
| 196 uint32_t size; |
| 197 |
| 198 TlclSendReceive(tpm_getflags_cmd.buffer, response, sizeof(response)); |
| 199 result = TpmReturnCode(response); |
| 200 if (result != TPM_SUCCESS) { |
| 201 return result; |
| 202 } |
| 203 FromTpmUint32(response + kTpmResponseHeaderLength, &size); |
| 204 assert(size == sizeof(TPM_PERMANENT_FLAGS)); |
| 205 pflags = |
| 206 (TPM_PERMANENT_FLAGS*) (response + kTpmResponseHeaderLength + sizeof(size)); |
| 207 *disable = pflags->disable; |
| 208 *deactivated = pflags->deactivated; |
| 209 return result; |
| 210 } |
| 211 |
| 212 uint32_t TlclSetGlobalLock(void) { |
| 213 uint32_t x; |
| 214 return TlclWrite(TPM_NV_INDEX0, (uint8_t*) &x, 0); |
| 215 } |
| 216 |
| 217 uint32_t TlclExtend(int pcr_num, uint8_t* in_digest, uint8_t* out_digest) { |
| 218 uint8_t response[kTpmResponseHeaderLength + kPcrDigestLength]; |
| 219 ToTpmUint32(tpm_extend_cmd.pcrNum, pcr_num); |
| 220 Memcpy(tpm_extend_cmd.inDigest, in_digest, kPcrDigestLength); |
| 221 TlclSendReceive(tpm_extend_cmd.buffer, response, sizeof(response)); |
| 222 Memcpy(out_digest, response + kTpmResponseHeaderLength, kPcrDigestLength); |
| 223 return TpmReturnCode(response); |
| 224 } |
| 225 |
| 226 uint32_t TlclGetPermissions(uint32_t index, uint32_t* permissions) { |
| 227 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; |
| 228 uint8_t* nvdata; |
| 229 uint32_t result; |
| 230 uint32_t size; |
| 231 |
| 232 ToTpmUint32(tpm_getpermissions_cmd.index, index); |
| 233 TlclSendReceive(tpm_getpermissions_cmd.buffer, response, sizeof(response)); |
| 234 result = TpmReturnCode(response); |
| 235 if (result != TPM_SUCCESS) { |
| 236 return result; |
| 237 } |
| 238 nvdata = response + kTpmResponseHeaderLength + sizeof(size); |
| 239 FromTpmUint32(nvdata + kNvDataPublicPermissionsOffset, permissions); |
| 240 return result; |
| 241 } |
OLD | NEW |