github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/src/tpm2/tpm2_lib.cc (about) 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <sys/types.h> 4 #include <sys/stat.h> 5 #include <fcntl.h> 6 #include <unistd.h> 7 #include <string.h> 8 #include <tpm20.h> 9 #include <tpm2_lib.h> 10 #include <errno.h> 11 #include <conversions.h> 12 13 #include <openssl/aes.h> 14 #include <openssl/rsa.h> 15 #include <openssl/x509.h> 16 #include <openssl_helpers.h> 17 #include <openssl/rand.h> 18 #include <openssl/hmac.h> 19 #include <openssl/sha.h> 20 21 #include <openssl_helpers.h> 22 23 #include <string> 24 using std::string; 25 26 27 // 28 // Copyright 2015 Google Corporation, All Rights Reserved. 29 // 30 // Licensed under the Apache License, Version 2.0 (the "License"); 31 // you may not use this file except in compliance with the License. 32 // You may obtain a copy of the License at 33 // http://www.apache.org/licenses/LICENSE-2.0 34 // or in the the file LICENSE-2.0.txt in the top level sourcedirectory 35 // Unless required by applicable law or agreed to in writing, software 36 // distributed under the License is distributed on an "AS IS" BASIS, 37 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 38 // See the License for the specific language governing permissions and 39 // limitations under the License 40 // 41 // Portions of this code were derived TPM2.0-TSS published 42 // by Intel under the license set forth in intel_license.txt 43 // and downloaded on or about August 6, 2015. 44 // File: tpm2_lib.cc 45 46 // standard buffer size 47 #define MAX_SIZE_PARAMS 4096 48 49 bool Equal(int size_in1, byte* in1, int size_in2, byte* in2) { 50 if(size_in1 != size_in2) 51 return false; 52 for (int i = 0; i < size_in1; i++) { 53 if (in1[i] != in2[i]) 54 return false; 55 } 56 return true; 57 } 58 59 void ReverseCpy(int size, byte* in, byte* out) { 60 out += size - 1; 61 for (int i = 0; i < size; i++) *(out--) = *(in++); 62 } 63 64 void PrintBytes(int n, byte* in) { 65 for (int i = 0; i < n; i++) printf("%02x", in[i]); 66 } 67 68 void ChangeEndian16(const uint16_t* in, uint16_t* out) { 69 byte* p_in = (byte*)in; 70 byte* p_out = (byte*)out; 71 72 p_out[0] = p_in[1]; 73 p_out[1] = p_in[0]; 74 } 75 76 void ChangeEndian32(const uint32_t* in, uint32_t* out) { 77 byte* p_in = (byte*)in; 78 byte* p_out = (byte*)out; 79 80 p_out[0] = p_in[3]; 81 p_out[1] = p_in[2]; 82 p_out[2] = p_in[1]; 83 p_out[3] = p_in[0]; 84 } 85 86 void ChangeEndian64(const uint64_t* in, uint64_t* out) { 87 byte* p_in = (byte*)in; 88 byte* p_out = (byte*)out; 89 90 p_out[0] = p_in[7]; 91 p_out[1] = p_in[6]; 92 p_out[2] = p_in[5]; 93 p_out[3] = p_in[4]; 94 p_out[4] = p_in[3]; 95 p_out[5] = p_in[2]; 96 p_out[6] = p_in[1]; 97 p_out[7] = p_in[0]; 98 } 99 100 bool ReadFileIntoBlock(const string& filename, int* size, byte* block) { 101 int fd = open(filename.c_str(), O_RDONLY); 102 if (fd < 0) 103 return false; 104 int n = read(fd, block, *size); 105 *size = n; 106 close(fd); 107 return true; 108 } 109 110 bool WriteFileFromBlock(const string& filename, int size, byte* block) { 111 int fd = creat(filename.c_str(), S_IRWXU | S_IRWXG); 112 if (fd < 0) 113 return false; 114 int n = write(fd, block, size); 115 close(fd); 116 return n > 0; 117 } 118 119 // Debug routines 120 void printCommand(const char* name, int size, byte* buf) { 121 printf("\n"); 122 printf("%s command: ", name); 123 PrintBytes(size, buf); 124 printf("\n"); 125 } 126 127 void printResponse(const char* name, uint16_t cap, uint32_t size, 128 uint32_t code, byte* buf) { 129 printf("%s response, ", name); 130 printf("cap: %04x, size: %08x, error code: %08x\n", cap, size, code); 131 PrintBytes(size, buf); 132 printf("\n\n"); 133 } 134 135 #define IF_LESS_THAN_RETURN_FALSE(x, y) if ((int)x < (int)y) return false; 136 #define IF_LESS_THAN_RETURN_MINUS1(x, y) if ((int)x < (int)y) return false; 137 #define IF_NEG_RETURN_FALSE(x) if (x < 0) return false; 138 #define IF_NEG_RETURN_MINUS1(x) if (x < 0) return -1; 139 140 void Update(int size, byte** ptr_buf, int* out_size, int* space_left) { 141 *ptr_buf += size; 142 *out_size += size; 143 *space_left -= size; 144 } 145 146 LocalTpm::LocalTpm() { 147 tpm_fd_ = -1; 148 } 149 150 LocalTpm::~LocalTpm() { 151 tpm_fd_ = -1; 152 } 153 154 bool LocalTpm::OpenTpm(const char* device) { 155 tpm_fd_ = open(device, O_RDWR); 156 return tpm_fd_ > 0; 157 } 158 159 void LocalTpm::CloseTpm() { 160 close(tpm_fd_); 161 tpm_fd_ = -1; 162 } 163 164 bool LocalTpm::SendCommand(int size, byte* command) { 165 int n = write(tpm_fd_, command, size); 166 if (n < 0) 167 printf("SendCommand Error: %s\n", strerror(errno)); 168 return n > 0; 169 } 170 171 bool LocalTpm::GetResponse(int* size, byte* response) { 172 int n = read(tpm_fd_, response, *size); 173 return n > 0; 174 } 175 176 int Tpm2_SetCommand(uint16_t tag, uint32_t cmd, byte* buf, 177 int size_param, byte* params) { 178 uint32_t size = sizeof(TPM2_COMMAND_HEADER) + size_param; 179 180 ChangeEndian16(&tag, &(((TPM2_COMMAND_HEADER*) buf)->tag)); 181 ChangeEndian32((uint32_t*)&size, &(((TPM2_COMMAND_HEADER*) buf)->paramSize)); 182 ChangeEndian32(&cmd, &(((TPM2_COMMAND_HEADER*) buf)->commandCode)); 183 memcpy(buf + sizeof(TPM2_COMMAND_HEADER), params, size_param); 184 return size; 185 } 186 187 #pragma pack(push, 1) 188 struct TPM_CAP_INPUT { 189 uint32_t cap_; 190 uint32_t prop_; 191 uint32_t count_; 192 }; 193 194 struct TPM_RESPONSE { 195 uint16_t cap_; 196 uint32_t responseSize_; 197 uint32_t responseCode_; 198 }; 199 #pragma pack(pop) 200 201 bool FillTpmPcrData(LocalTpm& tpm, TPMS_PCR_SELECTION pcrSelection, 202 int* size, byte* buf) { 203 TPML_PCR_SELECTION pcrSelect; 204 uint32_t updateCounter = 0; 205 TPML_PCR_SELECTION pcrSelectOut; 206 TPML_DIGEST digest; 207 208 pcrSelect.count = 1; 209 pcrSelect.pcrSelections[0] = pcrSelection; 210 211 if (!Tpm2_ReadPcrs(tpm, pcrSelect, &updateCounter, 212 &pcrSelectOut, &digest)) { 213 printf("FillTpmPcrData: Tpm2_ReadPcrs fails\n"); 214 return false; 215 } 216 int total_size = 0; 217 // ChangeEndian32(&digest.count, (uint32_t*)&buf[total_size]); 218 // total_size += sizeof(uint32_t); 219 for (int i = 0; i < (int)digest.count; i++) { 220 if ((int)(total_size + digest.digests[i].size + sizeof(uint16_t)) 221 > *size) { 222 printf("FillTpmPcrData: buffer too small\n"); 223 return false; 224 } 225 // ChangeEndian16(&digest.digests[i].size, (uint16_t*)&buf[total_size]); 226 // total_size += sizeof(uint16_t); 227 memcpy(&buf[total_size], digest.digests[i].buffer, 228 digest.digests[i].size); 229 total_size += digest.digests[i].size; 230 } 231 *size = total_size; 232 return true; 233 } 234 235 bool ComputePcrDigest(TPM_ALG_ID hash, int size_in, byte* in_buf, 236 int* size_out, byte* out) { 237 SHA_CTX sha1; 238 SHA256_CTX sha256; 239 240 if (hash != TPM_ALG_SHA1 && hash != TPM_ALG_SHA256) { 241 printf("ComputePcrDigest: unsupported hash algorithm\n"); 242 return false; 243 } 244 245 if (hash == TPM_ALG_SHA1) { 246 SHA1_Init(&sha1); 247 SHA1_Update(&sha1, in_buf, size_in); 248 SHA1_Final(out, &sha1); 249 *size_out = 20; 250 } else { 251 SHA256_Init(&sha256); 252 SHA256_Update(&sha256, in_buf, size_in); 253 SHA256_Final(out, &sha256); 254 *size_out = 32; 255 } 256 return true; 257 } 258 259 void Tpm2_InterpretResponse(int out_size, byte* out_buf, uint16_t* cap, 260 uint32_t* responseSize, uint32_t* responseCode) { 261 TPM_RESPONSE* r = (TPM_RESPONSE*)out_buf; 262 263 ChangeEndian16(&(r->cap_), cap); 264 ChangeEndian32(&(r->responseSize_), responseSize); 265 ChangeEndian32(&(r->responseCode_), responseCode); 266 } 267 268 bool Tpm2_Startup(LocalTpm& tpm) { 269 byte commandBuf[MAX_SIZE_PARAMS]; 270 271 TPM_SU state = TPM_SU_CLEAR; 272 TPM_SU big_endian_state; 273 ChangeEndian16(&state, &big_endian_state); 274 275 int in_size = Tpm2_SetCommand(TPM_ST_NO_SESSIONS, TPM_CC_Startup, 276 (byte*)commandBuf, sizeof(TPM_SU), 277 (byte*)&big_endian_state); 278 if (!tpm.SendCommand(in_size, (byte*)commandBuf)) { 279 printf("SendCommand failed\n"); 280 return false; 281 } 282 printCommand("Tpm2_Startup", in_size, commandBuf); 283 284 int resp_size = 128; 285 byte resp_buf[128]; 286 memset(resp_buf, 0, resp_size); 287 if (!tpm.GetResponse(&resp_size, resp_buf)) { 288 printf("GetResponse failed\n"); 289 return false; 290 } 291 292 uint16_t cap; 293 uint32_t responseSize; 294 uint32_t responseCode; 295 Tpm2_InterpretResponse(resp_size, resp_buf, &cap, 296 &responseSize, &responseCode); 297 printResponse("Tpm2_Startup", cap, responseSize, responseCode, resp_buf); 298 if (responseCode == RC_VER1) { 299 printf("TPM not initialized\n"); 300 } 301 if (responseCode != TPM_RC_SUCCESS) 302 return false; 303 return true; 304 } 305 306 bool Tpm2_Shutdown(LocalTpm& tpm) { 307 return true; 308 } 309 310 void PrintCapabilities(int size, byte* buf) { 311 uint32_t cap; 312 uint32_t property; 313 uint32_t value; 314 uint32_t count; 315 uint32_t handle; 316 byte* current_in = buf; 317 318 while (current_in < (size+buf)) { 319 if (*(current_in++) == 0) 320 break; 321 ChangeEndian32((uint32_t*)current_in, &cap); 322 current_in += sizeof(uint32_t); 323 if (cap == TPM_CAP_TPM_PROPERTIES) { 324 uint32_t i; 325 ChangeEndian32((uint32_t*)current_in, &count); 326 current_in += sizeof(uint32_t); 327 printf("%d properties:\n", count); 328 for (i = 0; i < count; i++) { 329 ChangeEndian32((uint32_t*)current_in, &property); 330 current_in += sizeof(uint32_t); 331 ChangeEndian32((uint32_t*)current_in, &value); 332 current_in += sizeof(uint32_t); 333 printf("\tproperty: %08x value: %08x\n", 334 property, value); 335 } 336 } else if (cap == TPM_CAP_HANDLES) { 337 uint32_t i; 338 ChangeEndian32((uint32_t*)current_in, &count); 339 current_in += sizeof(uint32_t); 340 printf("%d properties:\n", count); 341 for (i = 0; i < count; i++) { 342 ChangeEndian32((uint32_t*)current_in, &handle); 343 current_in += sizeof(uint32_t); 344 printf("\thandle: %08x\n", handle); 345 } 346 } else { 347 printf("unknown capability\n"); 348 return; 349 } 350 } 351 } 352 353 bool Tpm2_GetCapability(LocalTpm& tpm, uint32_t cap, uint32_t start, 354 int* out_size, byte* out_buf) { 355 byte commandBuf[2*MAX_SIZE_PARAMS]; 356 uint32_t count = 20; 357 uint32_t property = 0; 358 359 int resp_size = MAX_SIZE_PARAMS; 360 byte resp_buf[MAX_SIZE_PARAMS]; 361 int size_params = 0; 362 byte params[MAX_SIZE_PARAMS]; 363 byte* in = params; 364 int space_left = MAX_SIZE_PARAMS; 365 366 memset(resp_buf, 0, resp_size); 367 memset(out_buf, 0, *out_size); 368 369 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint32_t)) 370 ChangeEndian32(&cap, (uint32_t*)in); 371 Update(sizeof(uint32_t), &in, &size_params, &space_left); 372 if (cap == TPM_CAP_HANDLES) { 373 property = start; 374 } 375 376 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint32_t)) 377 ChangeEndian32(&property, (uint32_t*)in); 378 Update(sizeof(uint32_t), &in, &size_params, &space_left); 379 380 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint32_t)) 381 ChangeEndian32(&count, (uint32_t*)in); 382 Update(sizeof(uint32_t), &in, &size_params, &space_left); 383 384 int in_size = Tpm2_SetCommand(TPM_ST_NO_SESSIONS, TPM_CC_GetCapability, 385 commandBuf, size_params, params); 386 printCommand("GetCapability", in_size, commandBuf); 387 if (!tpm.SendCommand(in_size, commandBuf)) { 388 printf("SendCommand failed\n"); 389 return false; 390 } 391 if (!tpm.GetResponse(&resp_size, resp_buf)) { 392 printf("GetResponse failed\n"); 393 return false; 394 } 395 uint16_t cap2 = 0; 396 uint32_t responseSize; 397 uint32_t responseCode; 398 Tpm2_InterpretResponse(resp_size, resp_buf, &cap2, 399 &responseSize, &responseCode); 400 printResponse("GetCapability", cap, responseSize, responseCode, resp_buf); 401 if (responseCode != TPM_RC_SUCCESS) 402 return false; 403 *out_size = (int)(responseSize - sizeof(TPM_RESPONSE)); 404 memcpy(out_buf, resp_buf + sizeof(TPM_RESPONSE), *out_size); 405 return true; 406 } 407 408 bool Tpm2_GetRandom(LocalTpm& tpm, int numBytes, byte* buf) { 409 byte commandBuf[MAX_SIZE_PARAMS]; 410 411 uint16_t num_bytes = (uint16_t) numBytes; 412 uint16_t num_bytes_big_endian; 413 ChangeEndian16(&num_bytes, &num_bytes_big_endian); 414 415 int in_size = Tpm2_SetCommand(TPM_ST_NO_SESSIONS, TPM_CC_GetRandom, 416 (byte*)commandBuf, sizeof(uint16_t), 417 (byte*)&num_bytes_big_endian); 418 if (!tpm.SendCommand(in_size, (byte*)commandBuf)) { 419 printf("SendCommand failed\n"); 420 return false; 421 } 422 printCommand("GetRandom", in_size, commandBuf); 423 424 int resp_size = MAX_SIZE_PARAMS; 425 byte resp_buf[MAX_SIZE_PARAMS]; 426 memset(resp_buf, 0, resp_size); 427 if (!tpm.GetResponse(&resp_size, resp_buf)) { 428 printf("GetResponse failed\n"); 429 return false; 430 } 431 432 uint16_t cap; 433 uint32_t responseSize; 434 uint32_t responseCode; 435 Tpm2_InterpretResponse(resp_size, resp_buf, &cap, 436 &responseSize, &responseCode); 437 printResponse("GetRandom", cap, responseSize, responseCode, resp_buf); 438 if (responseCode != TPM_RC_SUCCESS) 439 return false; 440 byte* random_bytes = resp_buf + sizeof(TPM_RESPONSE); 441 int num = responseSize - sizeof(TPM_RESPONSE); 442 ReverseCpy(num, random_bytes, buf); 443 return true; 444 } 445 446 bool Tpm2_ReadClock(LocalTpm& tpm, uint64_t* current_time, uint64_t* current_clock) { 447 byte commandBuf[MAX_SIZE_PARAMS]; 448 449 memset(commandBuf, 0, MAX_SIZE_PARAMS); 450 int in_size = Tpm2_SetCommand(TPM_ST_NO_SESSIONS, TPM_CC_ReadClock, 451 (byte*)commandBuf, 0, nullptr); 452 if (!tpm.SendCommand(in_size, (byte*)commandBuf)) { 453 printf("SendCommand failed\n"); 454 return false; 455 } 456 printCommand("ReadClock", in_size, commandBuf); 457 458 int resp_size = MAX_SIZE_PARAMS; 459 byte resp_buf[MAX_SIZE_PARAMS]; 460 memset(resp_buf, 0, resp_size); 461 if (!tpm.GetResponse(&resp_size, resp_buf)) { 462 printf("GetResponse failed\n"); 463 return false; 464 } 465 466 uint16_t cap; 467 uint32_t responseSize; 468 uint32_t responseCode; 469 Tpm2_InterpretResponse(resp_size, resp_buf, &cap, 470 &responseSize, &responseCode); 471 printResponse("ReadClock", cap, responseSize, responseCode, resp_buf); 472 if (responseCode != TPM_RC_SUCCESS) 473 return false; 474 ChangeEndian64( 475 &((TPMS_TIME_INFO*) (resp_buf + sizeof(TPM_RESPONSE)))->time, 476 current_time); 477 ChangeEndian64( 478 (&((TPMS_TIME_INFO*) (resp_buf + sizeof(TPM_RESPONSE)))-> 479 clockInfo.clock), current_clock); 480 return true; 481 } 482 483 void setPcrBit(int pcrNum, byte* array) { 484 if (pcrNum >= 0 && pcrNum < PLATFORM_PCR) 485 array[pcrNum / 8] |= (1 << (pcrNum % 8)); 486 } 487 488 bool testPcrBit(int pcrNum, byte* array) { 489 return (array[pcrNum / 8] & (1 << (pcrNum % 8))) != 0; 490 } 491 492 bool GetPcrValue(int size, byte* in, uint32_t* updateCounter, 493 TPML_PCR_SELECTION* pcr_out, TPML_DIGEST* values) { 494 byte* current_in = in; 495 ChangeEndian32((uint32_t*)current_in, updateCounter); 496 current_in += sizeof(uint32_t); 497 ChangeEndian32((uint32_t*)current_in, &pcr_out->count); 498 current_in += sizeof(uint32_t); 499 for (int i = 0; i < static_cast<int>(pcr_out->count); i++) { 500 ChangeEndian16((uint16_t*)current_in, &pcr_out->pcrSelections[i].hash); 501 current_in += sizeof(uint16_t); 502 pcr_out->pcrSelections[i].sizeofSelect = *current_in; 503 current_in += 1; 504 memcpy(pcr_out->pcrSelections[i].pcrSelect, current_in, 505 pcr_out->pcrSelections[i].sizeofSelect); 506 current_in += pcr_out->pcrSelections[i].sizeofSelect; 507 } 508 509 ChangeEndian32((uint32_t*)current_in, &values->count); 510 current_in += sizeof(uint32_t); 511 for (int i = 0; i < static_cast<int>(values->count); i++) { 512 ChangeEndian16((uint16_t*)current_in, &values->digests[i].size); 513 current_in += sizeof(uint16_t); 514 memcpy(values->digests[i].buffer, current_in, values->digests[i].size); 515 current_in += values->digests[i].size; 516 } 517 518 return true; 519 } 520 521 void InitSinglePcrSelection(int pcrNum, TPM_ALG_ID hash, 522 TPML_PCR_SELECTION* pcrSelect) { 523 if (pcrNum == -1) { 524 pcrSelect->count = 0; 525 return; 526 } 527 pcrSelect->count = 1; 528 pcrSelect->pcrSelections[0].hash = hash; 529 pcrSelect->pcrSelections[0].sizeofSelect = 3; 530 for (int i = 0; i < 3; i++) 531 pcrSelect->pcrSelections[0].pcrSelect[i] = 0; 532 if (pcrNum != 0) 533 setPcrBit(pcrNum, pcrSelect->pcrSelections[0].pcrSelect); 534 } 535 536 bool Tpm2_ReadPcrs(LocalTpm& tpm, TPML_PCR_SELECTION pcrSelect, 537 uint32_t* updateCounter, 538 TPML_PCR_SELECTION* pcrSelectOut, TPML_DIGEST* values) { 539 byte commandBuf[2*MAX_SIZE_PARAMS]; 540 byte input_params[MAX_SIZE_PARAMS]; 541 int space_left = MAX_SIZE_PARAMS; 542 int resp_size = MAX_SIZE_PARAMS; 543 byte resp_buf[MAX_SIZE_PARAMS]; 544 int in_size = 0; 545 byte* in = input_params; 546 547 memset(resp_buf, 0, resp_size); 548 memset(input_params, 0, space_left); 549 550 // replace with long marshal_Pcr 551 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint32_t)) 552 ChangeEndian32(&pcrSelect.count, (uint32_t*)in); 553 Update(sizeof(uint32_t), &in, &in_size, &space_left); 554 555 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)) 556 ChangeEndian16(&pcrSelect.pcrSelections[0].hash, (uint16_t*)in); 557 Update(sizeof(uint16_t), &in, &in_size, &space_left); 558 559 IF_LESS_THAN_RETURN_FALSE(space_left, 1) 560 *in = pcrSelect.pcrSelections[0].sizeofSelect; 561 Update(1, &in, &in_size, &space_left); 562 563 IF_LESS_THAN_RETURN_FALSE(space_left, 3) 564 memcpy(in, pcrSelect.pcrSelections[0].pcrSelect, 3); 565 Update(3, &in, &in_size, &space_left); 566 567 int cmd_size = Tpm2_SetCommand(TPM_ST_NO_SESSIONS, TPM_CC_PCR_Read, 568 commandBuf, in_size, input_params); 569 if (!tpm.SendCommand(cmd_size, commandBuf)) { 570 printf("SendCommand failed\n"); 571 return false; 572 } 573 printCommand("ReadPcr", cmd_size, commandBuf); 574 575 if (!tpm.GetResponse(&resp_size, resp_buf)) { 576 printf("GetResponse failed\n"); 577 return false; 578 } 579 580 uint16_t cap = 0; 581 uint32_t responseSize; 582 uint32_t responseCode; 583 Tpm2_InterpretResponse(resp_size, resp_buf, &cap, 584 &responseSize, &responseCode); 585 printResponse("ReadPcr", cap, responseSize, responseCode, resp_buf); 586 if (responseCode != TPM_RC_SUCCESS) 587 return false; 588 return GetPcrValue(responseSize - sizeof(TPM_RESPONSE), 589 resp_buf + sizeof(TPM_RESPONSE), updateCounter, 590 pcrSelectOut, values); 591 } 592 593 bool Tpm2_ReadPcr(LocalTpm& tpm, int pcrNum, uint32_t* updateCounter, 594 TPML_PCR_SELECTION* pcrSelectOut, TPML_DIGEST* values) { 595 TPML_PCR_SELECTION pcrSelect; 596 InitSinglePcrSelection(pcrNum, TPM_ALG_SHA1, &pcrSelect); 597 return Tpm2_ReadPcrs(tpm, pcrSelect, updateCounter, 598 pcrSelectOut, values); 599 } 600 601 int SetOwnerHandle(TPM_HANDLE owner, int size, byte* buf) { 602 TPM_HANDLE handle = owner; 603 604 ChangeEndian32(&handle, (uint32_t*)buf); 605 return sizeof(TPM_HANDLE); 606 } 607 608 byte ToHex(const char in) { 609 if (in >= 0 && in <= '9') 610 return in - '0'; 611 if (in >= 'a' && in <= 'f') 612 return in - 'a' + 10; 613 if (in >= 'A' && in <= 'F') 614 return in - 'A' + 10; 615 return 0; 616 } 617 618 int SetPasswordData(string& password, int size, byte* buf) { 619 int num_auth_bytes = password.size() / 2; 620 int total_size = 0; 621 int space_left = size; 622 byte* out = buf; 623 624 byte auth[64]; 625 if (num_auth_bytes > 0 ) { 626 const char* str = password.c_str(); 627 byte c; 628 for (int i = 0; i < num_auth_bytes; i++) { 629 c = (ToHex(*str) << 4) | ToHex(*(str + 1)); 630 str += 2; 631 auth[i] = c; 632 } 633 } 634 uint16_t size_out = num_auth_bytes; 635 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint16_t)) 636 ChangeEndian16(&size_out, (uint16_t*)out); 637 Update(sizeof(uint16_t), &out, &total_size, &space_left); 638 if (num_auth_bytes > 0) { 639 IF_LESS_THAN_RETURN_MINUS1(space_left, num_auth_bytes) 640 memcpy(out, auth, num_auth_bytes); 641 Update(num_auth_bytes, &out, &total_size, &space_left); 642 } 643 return total_size; 644 } 645 646 int CreatePasswordAuthArea(string& password, int size, byte* buf) { 647 byte* out = buf; 648 int total_size = 0; 649 int space_left = size; 650 uint16_t len; 651 byte* pLen = out; 652 653 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint16_t)); 654 memset(out, 0, 2); 655 Update(sizeof(uint16_t), &out, &total_size, &space_left); 656 657 uint32_t policy = TPM_RS_PW; 658 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint32_t)); 659 ChangeEndian32(&policy, (uint32_t*)out); 660 Update(sizeof(uint32_t), &out, &total_size, &space_left); 661 662 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint16_t)); 663 memset(out, 0, sizeof(uint16_t)); 664 Update(sizeof(uint16_t), &out, &total_size, &space_left); 665 666 IF_LESS_THAN_RETURN_MINUS1(space_left, 1); 667 *out = 1; 668 Update(1, &out, &total_size, &space_left); 669 670 int n = SetPasswordData(password, size, out); 671 IF_NEG_RETURN_MINUS1(n) 672 Update(n, &out, &total_size, &space_left); 673 len = 7 + n; 674 ChangeEndian16(&len, (uint16_t*)pLen); 675 return total_size; 676 } 677 678 int CreateSensitiveArea(int size_in, byte* in, int size_data, byte* data, 679 int size, byte* buf) { 680 int total_size = 0; 681 int space_left = size; 682 byte* out = buf; 683 byte* pSize = out; 684 685 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint16_t)); 686 memset(out, 0, sizeof(uint16_t)); 687 Update(sizeof(uint16_t), &out, &total_size, &space_left); 688 689 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint16_t)); 690 ChangeEndian16((uint16_t*)&size_in, (uint16_t*)out); 691 Update(sizeof(uint16_t), &out, &total_size, &space_left); 692 if (size_in > 0) { 693 IF_LESS_THAN_RETURN_MINUS1(size_in, sizeof(uint16_t)); 694 memcpy(out, in, size_in); 695 Update(size_in, &out, &total_size, &space_left); 696 } 697 698 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint16_t)); 699 ChangeEndian16((uint16_t*)&size_data, (uint16_t*)out); 700 Update(sizeof(uint16_t), &out, &total_size, &space_left); 701 if (size_data > 0) { 702 IF_LESS_THAN_RETURN_MINUS1(size_data, sizeof(uint16_t)); 703 memcpy(out, data, size_data); 704 Update(size_data, &out, &total_size, &space_left); 705 } 706 707 uint16_t size_sensitive = total_size - sizeof(uint16_t); 708 ChangeEndian16((uint16_t*)&size_sensitive, (uint16_t*) pSize); 709 return total_size; 710 } 711 712 int CreateSensitiveArea(string& authString, int size_data, byte* data, 713 int size, byte* buf) { 714 int total_size = 0; 715 int space_left = size; 716 byte* out = buf; 717 byte* pSize = out; 718 719 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint16_t)); 720 memset(out, 0, sizeof(uint16_t)); 721 Update(sizeof(uint16_t), &out, &total_size, &space_left); 722 723 int n = SetPasswordData(authString, size, out); 724 IF_NEG_RETURN_MINUS1(n) 725 Update(n, &out, &total_size, &space_left); 726 727 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint16_t)); 728 ChangeEndian16((uint16_t*)&size_data, (uint16_t*)out); 729 Update(sizeof(uint16_t), &out, &total_size, &space_left); 730 if (size_data > 0) { 731 IF_LESS_THAN_RETURN_MINUS1(space_left, size_data); 732 memcpy(out, data, size_data); 733 Update(size_data, &out, &total_size, &space_left); 734 } 735 uint16_t size_sensitive = total_size - sizeof(uint16_t); 736 ChangeEndian16((uint16_t*)&size_sensitive, (uint16_t*) pSize); 737 return total_size; 738 } 739 740 bool Tpm2_PCR_Event(LocalTpm& tpm, int pcr_num, 741 uint16_t size_eventData, byte* eventData) { 742 byte commandBuf[2*MAX_SIZE_PARAMS]; 743 int input_size = 0; 744 int space_left = MAX_SIZE_PARAMS; 745 byte input_params[MAX_SIZE_PARAMS]; 746 byte* in = input_params; 747 int resp_size = MAX_SIZE_PARAMS; 748 byte resp_buf[MAX_SIZE_PARAMS]; 749 int n; 750 751 memset(resp_buf, 0, resp_size); 752 memset(input_params, 0, MAX_SIZE_PARAMS); 753 754 if (pcr_num < 0) { 755 printf("No PCR to update\n"); 756 return true; 757 } 758 759 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint32_t)) 760 ChangeEndian32((uint32_t*)&pcr_num, (uint32_t*)in); 761 Update(sizeof(uint32_t), &in, &input_size, &space_left); 762 763 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)) 764 memset(in, 0, sizeof(uint16_t)); 765 Update(sizeof(uint16_t), &in, &input_size, &space_left); 766 767 string emptyAuth; 768 n = CreatePasswordAuthArea(emptyAuth, MAX_SIZE_PARAMS, in); 769 IF_NEG_RETURN_FALSE(n); 770 Update(n, &in, &input_size, &space_left); 771 772 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)) 773 ChangeEndian16(&size_eventData, (uint16_t*)in); 774 Update(sizeof(uint16_t), &in, &input_size, &space_left); 775 776 IF_LESS_THAN_RETURN_FALSE(space_left, size_eventData) 777 memcpy(in, eventData, size_eventData); 778 Update(size_eventData, &in, &input_size, &space_left); 779 780 int in_size = Tpm2_SetCommand(TPM_ST_SESSIONS, TPM_CC_PCR_Event, 781 commandBuf, input_size, input_params); 782 if (!tpm.SendCommand(in_size, commandBuf)) { 783 printf("SendCommand failed\n"); 784 return false; 785 } 786 printCommand("PCR_Event", in_size, commandBuf); 787 788 if (!tpm.GetResponse(&resp_size, resp_buf)) { 789 printf("GetResponse failed\n"); 790 return false; 791 } 792 793 uint16_t cap = 0; 794 uint32_t responseSize; 795 uint32_t responseCode; 796 Tpm2_InterpretResponse(resp_size, resp_buf, &cap, 797 &responseSize, &responseCode); 798 printResponse("PCR_Event", cap, responseSize, responseCode, resp_buf); 799 if (responseCode != TPM_RC_SUCCESS) 800 return false; 801 return true; 802 } 803 804 int Marshal_AuthSession_Info(TPMI_DH_OBJECT& tpm_obj, TPMI_DH_ENTITY& bind_obj, 805 TPM2B_NONCE& initial_nonce, TPM2B_ENCRYPTED_SECRET& salt, 806 TPM_SE& session_type, TPMT_SYM_DEF& symmetric, 807 TPMI_ALG_HASH& hash_alg, int size, byte* out_buf) { 808 int total_size = 0; 809 int space_left = size; 810 byte* out = out_buf; 811 812 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint32_t)) 813 ChangeEndian32((uint32_t*)&tpm_obj, (uint32_t*)out); 814 Update(sizeof(uint32_t), &out, &total_size, &space_left); 815 816 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint32_t)) 817 ChangeEndian32((uint32_t*)&bind_obj, (uint32_t*)out); 818 Update(sizeof(uint32_t), &out, &total_size, &space_left); 819 820 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint16_t)) 821 ChangeEndian16((uint16_t*)&initial_nonce.size, (uint16_t*)out); 822 Update(sizeof(uint16_t), &out, &total_size, &space_left); 823 824 IF_LESS_THAN_RETURN_MINUS1(space_left, initial_nonce.size) 825 memcpy(out, initial_nonce.buffer, initial_nonce.size); 826 Update(initial_nonce.size, &out, &total_size, &space_left); 827 828 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint16_t)) 829 ChangeEndian16((uint16_t*)&salt.size, (uint16_t*)out); 830 Update(sizeof(uint16_t), &out, &total_size, &space_left); 831 832 IF_LESS_THAN_RETURN_MINUS1(space_left, salt.size) 833 memcpy(out, salt.secret, salt.size); 834 Update(salt.size, &out, &total_size, &space_left); 835 836 *out = session_type; 837 Update(1, &out, &total_size, &space_left); 838 839 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint16_t)) 840 ChangeEndian16((uint16_t*)&symmetric.algorithm, (uint16_t*)out); 841 Update(sizeof(uint16_t), &out, &total_size, &space_left); 842 843 if (symmetric.algorithm != TPM_ALG_NULL) { 844 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint16_t)) 845 ChangeEndian16((uint16_t*)&symmetric.keyBits.aes, (uint16_t*)out); 846 Update(sizeof(uint16_t), &out, &total_size, &space_left); 847 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint16_t)) 848 ChangeEndian16((uint16_t*)&symmetric.mode.aes, (uint16_t*)out); 849 Update(sizeof(uint16_t), &out, &total_size, &space_left); 850 } 851 852 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint16_t)) 853 ChangeEndian16((uint16_t*)&hash_alg, (uint16_t*)out); 854 Update(sizeof(uint16_t), &out, &total_size, &space_left); 855 return total_size; 856 } 857 858 int Marshal_Public_Key_Info(TPM2B_PUBLIC& in, int size, byte* buf) { 859 int total_size = 0; 860 int space_left = size; 861 byte* out = buf; 862 863 in.size = 10; 864 // symmetric is variable size 865 in.size += 2; 866 if (in.publicArea.parameters.rsaDetail.symmetric.algorithm != TPM_ALG_NULL) { 867 in.size += 2; 868 } 869 in.size += 12; 870 871 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint16_t)) 872 ChangeEndian16(&in.size, (uint16_t*)out); 873 Update(sizeof(uint16_t), &out, &total_size, &space_left); 874 875 // type 876 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint16_t)) 877 ChangeEndian16(&in.publicArea.type, (uint16_t*)out); 878 Update(sizeof(uint16_t), &out, &total_size, &space_left); 879 880 //alg 881 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint16_t)) 882 ChangeEndian16(&in.publicArea.nameAlg, (uint16_t*)out); 883 Update(sizeof(uint16_t), &out, &total_size, &space_left); 884 885 // attributes 886 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint32_t)) 887 ChangeEndian32((uint32_t*)&in.publicArea.objectAttributes, (uint32_t*)out); 888 Update(sizeof(uint32_t), &out, &total_size, &space_left); 889 890 // auth size 891 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint16_t)) 892 memset(out, 0, sizeof(uint16_t)); 893 Update(sizeof(uint16_t), &out, &total_size, &space_left); 894 895 // algorithm 896 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint16_t)) 897 ChangeEndian16((uint16_t*)&in.publicArea.parameters.rsaDetail.symmetric.algorithm, 898 (uint16_t*)out); 899 Update(sizeof(uint16_t), &out, &total_size, &space_left); 900 if (in.publicArea.parameters.rsaDetail.symmetric.algorithm != TPM_ALG_NULL) { 901 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint16_t)) 902 ChangeEndian16((uint16_t*)&in.publicArea.parameters.rsaDetail.symmetric.keyBits.aes, 903 (uint16_t*)out); 904 Update(sizeof(uint16_t), &out, &total_size, &space_left); 905 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint16_t)) 906 ChangeEndian16((uint16_t*)&in.publicArea.parameters.rsaDetail.symmetric.mode.aes, 907 (uint16_t*)out); 908 Update(sizeof(uint16_t), &out, &total_size, &space_left); 909 } 910 911 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint16_t)) 912 ChangeEndian16((uint16_t*)&in.publicArea.parameters.rsaDetail.scheme.scheme, 913 (uint16_t*)out); 914 Update(sizeof(uint16_t), &out, &total_size, &space_left); 915 916 if (in.publicArea.parameters.rsaDetail.scheme.scheme == TPM_ALG_RSASSA) { 917 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint16_t)) 918 ChangeEndian16( 919 &in.publicArea.parameters.rsaDetail.scheme.details.rsassa.hashAlg, 920 (uint16_t*)out); 921 Update(sizeof(uint16_t), &out, &total_size, &space_left); 922 } 923 924 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint16_t)) 925 ChangeEndian16((uint16_t*)&in.publicArea.parameters.rsaDetail.keyBits, 926 (uint16_t*)out); 927 Update(sizeof(uint16_t), &out, &total_size, &space_left); 928 929 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint32_t)) 930 ChangeEndian32((uint32_t*)&in.publicArea.parameters.rsaDetail.exponent, 931 (uint32_t*)out); 932 Update(sizeof(uint32_t), &out, &total_size, &space_left); 933 934 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint16_t)) 935 memset(out, 0, 2); 936 Update(sizeof(uint16_t), &out, &total_size, &space_left); 937 return total_size; 938 } 939 940 int Marshal_OutsideInfo(TPM2B_DATA& in, int size, byte* buf) { 941 int total_size = 0; 942 int space_left = size; 943 byte* out = buf; 944 945 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint16_t)) 946 ChangeEndian16(&in.size, (uint16_t*) out); 947 Update(sizeof(uint16_t), &out, &total_size, &space_left); 948 949 IF_LESS_THAN_RETURN_MINUS1(space_left, in.size) 950 memcpy(out, in.buffer, in.size); 951 Update(in.size, &out, &total_size, &space_left); 952 return total_size; 953 } 954 955 int Marshal_PCR_Long_Selection(TPML_PCR_SELECTION& in, int size, byte* buf) { 956 int total_size = 0; 957 int space_left = size; 958 byte* out = buf; 959 960 if (in.count == 0) { 961 memset(out, 0, sizeof(uint32_t)); 962 return sizeof(uint32_t); 963 } 964 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint32_t)) 965 ChangeEndian32(&in.count, (uint32_t*)out); 966 Update(sizeof(uint32_t), &out, &total_size, &space_left); 967 968 for (int i = 0; i < static_cast<int>(in.count); i++) { 969 970 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint16_t)) 971 ChangeEndian16(&in.pcrSelections[i].hash, (uint16_t*)out); 972 Update(sizeof(uint16_t), &out, &total_size, &space_left); 973 974 IF_LESS_THAN_RETURN_MINUS1(space_left, 1) 975 *out = in.pcrSelections[i].sizeofSelect; 976 Update(1, &out, &total_size, &space_left); 977 978 IF_LESS_THAN_RETURN_MINUS1(space_left, in.pcrSelections[i].sizeofSelect) 979 memcpy(out, in.pcrSelections[i].pcrSelect, 980 in.pcrSelections[i].sizeofSelect); 981 Update(in.pcrSelections[i].sizeofSelect, &out, &total_size, &space_left); 982 } 983 return total_size; 984 } 985 986 int Marshal_PCR_Short_Selection(TPMS_PCR_SELECTION& in, int size, byte* buf) { 987 byte* out = buf; 988 int total_size = 0; 989 int space_left = size; 990 991 IF_LESS_THAN_RETURN_MINUS1(space_left, 1) 992 *out = in.sizeofSelect; 993 Update(1, &out, &total_size, &space_left); 994 995 IF_LESS_THAN_RETURN_MINUS1(space_left, in.sizeofSelect) 996 memcpy(out, in.pcrSelect, in.sizeofSelect); 997 Update(in.sizeofSelect, &out, &total_size, &space_left); 998 return total_size; 999 } 1000 1001 int Marshal_Signature_Scheme_Info(TPMT_SIG_SCHEME& sig_scheme, int size, 1002 byte* buf) { 1003 int total_size = 0; 1004 int space_left = size; 1005 byte* out = buf; 1006 1007 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint16_t)) 1008 ChangeEndian16(&sig_scheme.scheme, (uint16_t*)out); 1009 Update(sizeof(uint16_t), &out, &total_size, &space_left); 1010 1011 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint16_t)) 1012 ChangeEndian16(&sig_scheme.details.rsassa.hashAlg, (uint16_t*)out); 1013 Update(sizeof(uint16_t), &out, &total_size, &space_left); 1014 return total_size; 1015 } 1016 1017 int Marshal_Keyed_Hash_Info(TPM2B_PUBLIC& keyed_hash, int size, byte* buf) { 1018 int total_size = 0; 1019 int space_left = size; 1020 byte* out = buf; 1021 byte* pSize = out; 1022 1023 // size to fill in later 1024 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint16_t)) 1025 memset(out, 0, 2); 1026 Update(sizeof(uint16_t), &out, &total_size, &space_left); 1027 1028 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint16_t)) 1029 ChangeEndian16(&keyed_hash.publicArea.type, (uint16_t*)out); 1030 Update(sizeof(uint16_t), &out, &total_size, &space_left); 1031 1032 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint16_t)) 1033 ChangeEndian16(&keyed_hash.publicArea.nameAlg, (uint16_t*)out); 1034 Update(sizeof(uint16_t), &out, &total_size, &space_left); 1035 1036 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint32_t)) 1037 ChangeEndian32((uint32_t*)&keyed_hash.publicArea.objectAttributes, 1038 (uint32_t*)out); 1039 Update(sizeof(uint32_t), &out, &total_size, &space_left); 1040 1041 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint16_t)) 1042 ChangeEndian16(&keyed_hash.publicArea.authPolicy.size, 1043 (uint16_t*)out); 1044 Update(sizeof(uint16_t), &out, &total_size, &space_left); 1045 1046 IF_LESS_THAN_RETURN_MINUS1(space_left, keyed_hash.publicArea.authPolicy.size) 1047 memcpy(out, keyed_hash.publicArea.authPolicy.buffer, 1048 keyed_hash.publicArea.authPolicy.size); 1049 Update(keyed_hash.publicArea.authPolicy.size, &out, &total_size, &space_left); 1050 1051 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint16_t)) 1052 ChangeEndian16(&keyed_hash.publicArea.parameters.keyedHashDetail.scheme.scheme, 1053 (uint16_t*)out); 1054 Update(sizeof(uint16_t), &out, &total_size, &space_left); 1055 1056 // public id 1057 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint16_t)) 1058 memset(out, 0, sizeof(uint16_t)); 1059 Update(sizeof(uint16_t), &out, &total_size, &space_left); 1060 1061 uint16_t size_publicArea = total_size - sizeof(uint16_t); 1062 ChangeEndian16(&size_publicArea, (uint16_t*)pSize); 1063 return total_size; 1064 } 1065 1066 void FillPublicRsaTemplate(TPM_ALG_ID enc_alg, TPM_ALG_ID int_alg, 1067 TPMA_OBJECT flags, TPM_ALG_ID sym_alg, 1068 TPMI_AES_KEY_BITS sym_key_size, 1069 TPMI_ALG_SYM_MODE sym_mode, TPM_ALG_ID sig_scheme, 1070 int mod_size, uint32_t exp, TPM2B_PUBLIC& pub_key) { 1071 pub_key.publicArea.type = enc_alg; 1072 pub_key.publicArea.nameAlg = int_alg; 1073 pub_key.publicArea.objectAttributes = flags; 1074 pub_key.publicArea.parameters.rsaDetail.symmetric.algorithm = sym_alg; 1075 if (sym_alg != TPM_ALG_NULL) { 1076 pub_key.publicArea.parameters.rsaDetail.symmetric.keyBits.aes = sym_key_size; 1077 pub_key.publicArea.parameters.rsaDetail.symmetric.mode.aes = sym_mode; 1078 } 1079 pub_key.publicArea.parameters.rsaDetail.scheme.scheme = sig_scheme; 1080 if (sig_scheme != TPM_ALG_NULL) 1081 pub_key.publicArea.parameters.rsaDetail.scheme.details.rsassa.hashAlg = 0x04; 1082 pub_key.publicArea.parameters.rsaDetail.keyBits = (uint16_t)mod_size; 1083 pub_key.publicArea.parameters.rsaDetail.exponent = exp; 1084 } 1085 1086 void FillEmptyData(TPM2B_DATA& data) { 1087 data.size = 0; 1088 } 1089 1090 void FillSignatureSchemeTemplate(TPM_ALG_ID enc_alg, TPM_ALG_ID int_alg, 1091 TPMT_SIG_SCHEME& scheme) { 1092 scheme.scheme = enc_alg; 1093 scheme.details.rsassa.hashAlg= int_alg; 1094 } 1095 1096 void FillKeyedHashTemplate(TPM_ALG_ID enc_alg, TPM_ALG_ID int_alg, 1097 TPMA_OBJECT flags, uint16_t size_auth, byte* auth, 1098 TPM2B_PUBLIC& keyed_hash) { 1099 keyed_hash.publicArea.type = enc_alg; 1100 keyed_hash.publicArea.nameAlg = int_alg; 1101 keyed_hash.publicArea.objectAttributes = flags; 1102 keyed_hash.publicArea.authPolicy.size = size_auth; 1103 memcpy(keyed_hash.publicArea.authPolicy.buffer, auth, size_auth); 1104 keyed_hash.publicArea.authPolicy.size = size_auth; 1105 keyed_hash.publicArea.parameters.keyedHashDetail.scheme.scheme = TPM_ALG_NULL; 1106 } 1107 1108 bool GetPublicOut(int size, byte* in, TPM_HANDLE* handle, TPM2B_PUBLIC* pub_out, 1109 TPM2B_CREATION_DATA* creation_data, TPM2B_DIGEST* hash, 1110 TPMT_TK_CREATION* creation_ticket, TPM2B_NAME* name) { 1111 byte* current_in = in; 1112 ChangeEndian32((uint32_t*)current_in, (uint32_t*)handle); 1113 current_in += sizeof(TPM_HANDLE); 1114 1115 // skip size and 2 uint16_t's 1116 current_in += 3 * sizeof(uint16_t); 1117 uint16_t new_size; 1118 ChangeEndian16((uint16_t*)current_in, 1119 (uint16_t*)&pub_out->publicArea.type); 1120 current_in += sizeof(uint16_t); 1121 ChangeEndian16((uint16_t*)current_in, 1122 (uint16_t*)&pub_out->publicArea.nameAlg); 1123 current_in += sizeof(uint16_t); 1124 1125 ChangeEndian32((uint32_t*)current_in, 1126 (uint32_t*)&pub_out->publicArea.objectAttributes); 1127 current_in += sizeof(uint32_t); 1128 1129 ChangeEndian32((uint32_t*)current_in, 1130 (uint32_t*)&pub_out->publicArea.parameters.rsaDetail.symmetric.algorithm); 1131 current_in += sizeof(uint32_t); 1132 if (pub_out->publicArea.parameters.rsaDetail.symmetric.algorithm != TPM_ALG_NULL) { 1133 } 1134 ChangeEndian16((uint16_t*)current_in, 1135 (uint16_t*)&pub_out->publicArea.parameters.rsaDetail.scheme.scheme); 1136 current_in += sizeof(uint16_t); 1137 ChangeEndian16((uint16_t*)current_in, 1138 (uint16_t*)&pub_out->publicArea.parameters.rsaDetail.scheme.details); 1139 current_in += sizeof(uint16_t); 1140 1141 ChangeEndian16((uint16_t*)current_in, 1142 &pub_out->publicArea.parameters.rsaDetail.keyBits); 1143 current_in += sizeof(uint16_t); 1144 ChangeEndian32((uint32_t*)current_in, 1145 &pub_out->publicArea.parameters.rsaDetail.exponent); 1146 current_in += sizeof(uint32_t); 1147 1148 // get modulus 1149 ChangeEndian16((uint16_t*)current_in, &new_size); 1150 pub_out->publicArea.unique.rsa.size = new_size; 1151 current_in += sizeof(uint16_t); 1152 memcpy(pub_out->publicArea.unique.rsa.buffer, current_in, new_size); 1153 current_in += new_size; 1154 1155 return true; 1156 } 1157 1158 bool Tpm2_CreatePrimary(LocalTpm& tpm, TPM_HANDLE owner, string& authString, 1159 TPML_PCR_SELECTION& pcr_selection, 1160 TPM_ALG_ID enc_alg, TPM_ALG_ID int_alg, 1161 TPMA_OBJECT& flags, TPM_ALG_ID sym_alg, 1162 TPMI_AES_KEY_BITS sym_key_size, 1163 TPMI_ALG_SYM_MODE sym_mode, TPM_ALG_ID sig_scheme, 1164 int mod_size, uint32_t exp, 1165 TPM_HANDLE* handle, TPM2B_PUBLIC* pub_out) { 1166 byte commandBuf[2*MAX_SIZE_PARAMS]; 1167 1168 byte params[MAX_SIZE_PARAMS]; 1169 byte* out = params; 1170 int size_params = 0; 1171 int space_left = MAX_SIZE_PARAMS; 1172 int n; 1173 1174 memset(commandBuf, 0, 2*MAX_SIZE_PARAMS); 1175 memset(params, 0, MAX_SIZE_PARAMS); 1176 1177 n = SetOwnerHandle(owner, space_left, out); 1178 IF_NEG_RETURN_FALSE(n); 1179 Update(n, &out, &size_params, &space_left); 1180 1181 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)) 1182 memset(out, 0, sizeof(uint16_t)); 1183 Update(sizeof(uint16_t), &out, &size_params, &space_left); 1184 1185 string emptyAuth; 1186 n = CreatePasswordAuthArea(emptyAuth, space_left, out); 1187 IF_NEG_RETURN_FALSE(n); 1188 Update(n, &out, &size_params, &space_left); 1189 1190 n = CreateSensitiveArea(authString, 0, NULL, space_left, out); 1191 IF_NEG_RETURN_FALSE(n); 1192 Update(n, &out, &size_params, &space_left); 1193 1194 TPM2B_PUBLIC pub_key; 1195 FillPublicRsaTemplate(enc_alg, int_alg, flags, sym_alg, 1196 sym_key_size, sym_mode, sig_scheme, 1197 mod_size, exp, pub_key); 1198 n = Marshal_Public_Key_Info(pub_key, space_left, out); 1199 IF_NEG_RETURN_FALSE(n); 1200 Update(n, &out, &size_params, &space_left); 1201 1202 TPM2B_DATA data; 1203 FillEmptyData(data); 1204 n = Marshal_OutsideInfo(data, space_left, out); 1205 IF_NEG_RETURN_FALSE(n); 1206 Update(n, &out, &size_params, &space_left); 1207 1208 n = Marshal_PCR_Long_Selection(pcr_selection, space_left, out); 1209 IF_NEG_RETURN_FALSE(n); 1210 Update(n, &out, &size_params, &space_left); 1211 int in_size = Tpm2_SetCommand(TPM_ST_SESSIONS, TPM_CC_CreatePrimary, 1212 (byte*)commandBuf, 1213 size_params, 1214 (byte*)params); 1215 if (!tpm.SendCommand(in_size, (byte*)commandBuf)) { 1216 printf("SendCommand failed\n"); 1217 return false; 1218 } 1219 printCommand("CreatePrimary", in_size, commandBuf); 1220 1221 int resp_size = MAX_SIZE_PARAMS; 1222 byte resp_buf[MAX_SIZE_PARAMS]; 1223 memset(resp_buf, 0, resp_size); 1224 if (!tpm.GetResponse(&resp_size, resp_buf)) { 1225 printf("GetResponse failed\n"); 1226 return false; 1227 } 1228 1229 uint16_t cap; 1230 uint32_t responseSize; 1231 uint32_t responseCode; 1232 Tpm2_InterpretResponse(resp_size, resp_buf, &cap, 1233 &responseSize, &responseCode); 1234 printResponse("CreatePrimary", cap, responseSize, responseCode, resp_buf); 1235 if (responseCode != TPM_RC_SUCCESS) 1236 return false; 1237 1238 TPM2B_CREATION_DATA creation_data; 1239 TPM2B_DIGEST hash; 1240 TPMT_TK_CREATION creation_ticket; 1241 TPM2B_NAME name; 1242 return GetPublicOut(responseSize - sizeof(TPM_RESPONSE), 1243 &resp_buf[sizeof(TPM_RESPONSE)], handle, 1244 pub_out, &creation_data, 1245 &hash, &creation_ticket, &name); 1246 } 1247 1248 bool GetLoadOut(int size, byte* in, TPM_HANDLE* new_handle, TPM2B_NAME* name) { 1249 byte* current_in = in; 1250 1251 ChangeEndian32((uint32_t*)current_in, (uint32_t*)new_handle); 1252 current_in += sizeof(uint32_t); 1253 ChangeEndian16((uint16_t*)current_in, (uint16_t*)&name->size); 1254 current_in += sizeof(uint16_t); 1255 memcpy(name->name, current_in, name->size); 1256 current_in += name->size; 1257 return true; 1258 } 1259 1260 bool Tpm2_PolicySecret(LocalTpm& tpm, TPM_HANDLE handle, 1261 TPM2B_DIGEST* policy_digest, 1262 TPM2B_TIMEOUT* timeout, 1263 TPMT_TK_AUTH* ticket) { 1264 byte commandBuf[2*MAX_SIZE_PARAMS]; 1265 1266 int resp_size = MAX_SIZE_PARAMS; 1267 byte resp_buf[MAX_SIZE_PARAMS]; 1268 byte params[MAX_SIZE_PARAMS]; 1269 byte* in = params; 1270 int total_size = 0; 1271 int space_left = MAX_SIZE_PARAMS; 1272 1273 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint32_t)) 1274 ChangeEndian32((uint32_t*)&handle, (uint32_t*)in); 1275 Update(sizeof(uint32_t), &in, &total_size, &space_left); 1276 1277 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)) 1278 ChangeEndian16((uint16_t*)&policy_digest->size, (uint16_t*)in); 1279 Update(sizeof(uint16_t), &in, &total_size, &space_left); 1280 1281 IF_LESS_THAN_RETURN_FALSE(space_left, policy_digest->size) 1282 memcpy(in, policy_digest->buffer, policy_digest->size); 1283 Update(policy_digest->size, &in, &total_size, &space_left); 1284 1285 int in_size = Tpm2_SetCommand(TPM_ST_NO_SESSIONS, TPM_CC_PolicySecret, 1286 commandBuf, total_size, params); 1287 printCommand("PolicySecret", in_size, commandBuf); 1288 if (!tpm.SendCommand(in_size, commandBuf)) { 1289 printf("SendCommand failed\n"); 1290 return false; 1291 } 1292 if (!tpm.GetResponse(&resp_size, resp_buf)) { 1293 printf("GetResponse failed\n"); 1294 return false; 1295 } 1296 uint16_t cap = 0; 1297 uint32_t responseSize; 1298 uint32_t responseCode; 1299 Tpm2_InterpretResponse(resp_size, resp_buf, &cap, 1300 &responseSize, &responseCode); 1301 printResponse("PolicySecret", cap, responseSize, responseCode, resp_buf); 1302 if (responseCode != TPM_RC_SUCCESS) 1303 return false; 1304 return true; 1305 } 1306 1307 bool Tpm2_PolicyPassword(LocalTpm& tpm, TPM_HANDLE handle) { 1308 byte commandBuf[2*MAX_SIZE_PARAMS]; 1309 1310 int resp_size = MAX_SIZE_PARAMS; 1311 byte resp_buf[MAX_SIZE_PARAMS]; 1312 byte params[MAX_SIZE_PARAMS]; 1313 byte* current_out = params; 1314 int total_size = 0; 1315 1316 ChangeEndian32((uint32_t*)&handle, (uint32_t*)current_out); 1317 current_out += sizeof(uint32_t); 1318 total_size += sizeof(uint32_t); 1319 1320 int in_size = Tpm2_SetCommand(TPM_ST_NO_SESSIONS, TPM_CC_PolicyPassword, 1321 commandBuf, total_size, params); 1322 printCommand("PolicyPassword", in_size, commandBuf); 1323 if (!tpm.SendCommand(in_size, commandBuf)) { 1324 printf("SendCommand failed\n"); 1325 return false; 1326 } 1327 if (!tpm.GetResponse(&resp_size, resp_buf)) { 1328 printf("GetResponse failed\n"); 1329 return false; 1330 } 1331 uint16_t cap = 0; 1332 uint32_t responseSize; 1333 uint32_t responseCode; 1334 Tpm2_InterpretResponse(resp_size, resp_buf, &cap, 1335 &responseSize, &responseCode); 1336 printResponse("PolicyPassword", cap, responseSize, responseCode, resp_buf); 1337 if (responseCode != TPM_RC_SUCCESS) 1338 return false; 1339 return true; 1340 } 1341 1342 bool Tpm2_PolicyGetDigest(LocalTpm& tpm, TPM_HANDLE handle, TPM2B_DIGEST* digest_out) { 1343 byte commandBuf[2*MAX_SIZE_PARAMS]; 1344 1345 int resp_size = MAX_SIZE_PARAMS; 1346 byte resp_buf[MAX_SIZE_PARAMS]; 1347 int size_params = 0; 1348 byte params[MAX_SIZE_PARAMS]; 1349 1350 memset(resp_buf, 0, resp_size); 1351 1352 ChangeEndian32(&handle, (uint32_t*)params); 1353 size_params += sizeof(uint32_t); 1354 int in_size = Tpm2_SetCommand(TPM_ST_NO_SESSIONS, TPM_CC_PolicyGetDigest, 1355 commandBuf, size_params, params); 1356 printCommand("PolicyGetDigest", in_size, commandBuf); 1357 if (!tpm.SendCommand(in_size, commandBuf)) { 1358 printf("SendCommand failed\n"); 1359 return false; 1360 } 1361 if (!tpm.GetResponse(&resp_size, resp_buf)) { 1362 printf("GetResponse failed\n"); 1363 return false; 1364 } 1365 uint16_t cap = 0; 1366 uint32_t responseSize; 1367 uint32_t responseCode; 1368 Tpm2_InterpretResponse(resp_size, resp_buf, &cap, 1369 &responseSize, &responseCode); 1370 printResponse("PolicyGetDigest", cap, responseSize, responseCode, resp_buf); 1371 if (responseCode != TPM_RC_SUCCESS) 1372 return false; 1373 byte* current_in = resp_buf + sizeof(TPM_RESPONSE); 1374 ChangeEndian16((uint16_t*)current_in, &digest_out->size); 1375 current_in += sizeof(uint16_t); 1376 memcpy(digest_out->buffer, current_in, digest_out->size); 1377 return true; 1378 } 1379 1380 bool Tpm2_StartAuthSession(LocalTpm& tpm, TPM_RH tpm_obj, TPM_RH bind_obj, 1381 TPM2B_NONCE& initial_nonce, 1382 TPM2B_ENCRYPTED_SECRET& salt, 1383 TPM_SE session_type, TPMT_SYM_DEF& symmetric, 1384 TPMI_ALG_HASH hash_alg, TPM_HANDLE* session_handle, 1385 TPM2B_NONCE* nonce_obj) { 1386 byte commandBuf[2*MAX_SIZE_PARAMS]; 1387 int resp_size = MAX_SIZE_PARAMS; 1388 byte resp_buf[MAX_SIZE_PARAMS]; 1389 int size_params = 0; 1390 byte params[MAX_SIZE_PARAMS]; 1391 byte* in = params; 1392 int space_left = MAX_SIZE_PARAMS; 1393 1394 memset(params, 0, MAX_SIZE_PARAMS); 1395 1396 int n= Marshal_AuthSession_Info(tpm_obj, bind_obj, initial_nonce, 1397 salt, session_type, symmetric, hash_alg, 1398 MAX_SIZE_PARAMS, params); 1399 IF_NEG_RETURN_FALSE(n); 1400 Update(n, &in, &size_params, &space_left); 1401 int in_size = Tpm2_SetCommand(TPM_ST_NO_SESSIONS, TPM_CC_StartAuthSession, 1402 commandBuf, size_params, params); 1403 printCommand("StartAuthSession", in_size, commandBuf); 1404 if (!tpm.SendCommand(in_size, commandBuf)) { 1405 printf("SendCommand failed\n"); 1406 return false; 1407 } 1408 if (!tpm.GetResponse(&resp_size, resp_buf)) { 1409 printf("GetResponse failed\n"); 1410 return false; 1411 } 1412 uint16_t cap = 0; 1413 uint32_t responseSize; 1414 uint32_t responseCode; 1415 Tpm2_InterpretResponse(resp_size, resp_buf, &cap, 1416 &responseSize, &responseCode); 1417 printResponse("StartAuthSession", cap, responseSize, responseCode, resp_buf); 1418 if (responseCode != TPM_RC_SUCCESS) 1419 return false; 1420 byte* current_out = resp_buf + sizeof(TPM_RESPONSE); 1421 ChangeEndian32((uint32_t*)current_out, (uint32_t*)session_handle); 1422 current_out += sizeof(uint32_t); 1423 ChangeEndian16((uint16_t*)current_out, &nonce_obj->size); 1424 current_out += sizeof(uint16_t); 1425 memcpy(nonce_obj->buffer, current_out, nonce_obj->size); 1426 return true; 1427 } 1428 1429 bool Tpm2_PolicyPcr(LocalTpm& tpm, TPM_HANDLE session_handle, 1430 TPM2B_DIGEST& expected_digest, TPML_PCR_SELECTION& pcr) { 1431 byte commandBuf[2*MAX_SIZE_PARAMS]; 1432 1433 int resp_size = MAX_SIZE_PARAMS; 1434 byte resp_buf[MAX_SIZE_PARAMS]; 1435 byte params[MAX_SIZE_PARAMS]; 1436 byte* out = params; 1437 int total_size = 0; 1438 int space_left = MAX_SIZE_PARAMS; 1439 1440 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint32_t)); 1441 ChangeEndian32((uint32_t*)&session_handle, (uint32_t*)out); 1442 Update(sizeof(uint32_t), &out, &total_size, &space_left); 1443 1444 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)); 1445 ChangeEndian16(&expected_digest.size, (uint16_t*)out); 1446 Update(sizeof(uint16_t), &out, &total_size, &space_left); 1447 1448 int n = Marshal_PCR_Long_Selection(pcr, MAX_SIZE_PARAMS, out); 1449 IF_NEG_RETURN_FALSE(n) 1450 Update(n, &out, &total_size, &space_left); 1451 int in_size = Tpm2_SetCommand(TPM_ST_NO_SESSIONS, TPM_CC_PolicyPCR, 1452 commandBuf, total_size, params); 1453 printCommand("PolicyPcr", in_size, commandBuf); 1454 if (!tpm.SendCommand(in_size, commandBuf)) { 1455 printf("SendCommand failed\n"); 1456 return false; 1457 } 1458 if (!tpm.GetResponse(&resp_size, resp_buf)) { 1459 printf("GetResponse failed\n"); 1460 return false; 1461 } 1462 uint16_t cap = 0; 1463 uint32_t responseSize; 1464 uint32_t responseCode; 1465 Tpm2_InterpretResponse(resp_size, resp_buf, &cap, 1466 &responseSize, &responseCode); 1467 printResponse("PolicyPcr", cap, responseSize, responseCode, resp_buf); 1468 if (responseCode != TPM_RC_SUCCESS) 1469 return false; 1470 return true; 1471 } 1472 1473 bool Tpm2_MakeCredential(LocalTpm& tpm, 1474 TPM_HANDLE keyHandle, 1475 TPM2B_DIGEST& credential, 1476 TPM2B_NAME& objectName, 1477 TPM2B_ID_OBJECT* credentialBlob, 1478 TPM2B_ENCRYPTED_SECRET* secret) { 1479 byte commandBuf[2*MAX_SIZE_PARAMS]; 1480 int resp_size = MAX_SIZE_PARAMS; 1481 byte resp_buf[MAX_SIZE_PARAMS]; 1482 byte params[MAX_SIZE_PARAMS]; 1483 byte* in = params; 1484 int total_size = 0; 1485 int space_left = MAX_SIZE_PARAMS; 1486 1487 memset(params, 0, MAX_SIZE_PARAMS); 1488 memset(resp_buf, 0, MAX_SIZE_PARAMS); 1489 1490 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint32_t)) 1491 ChangeEndian32((uint32_t*)&keyHandle, (uint32_t*)in); 1492 Update(sizeof(uint32_t), &in, &total_size, &space_left); 1493 1494 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)) 1495 ChangeEndian16((uint16_t*)&credential.size, (uint16_t*)in); 1496 Update(sizeof(uint16_t), &in, &total_size, &space_left); 1497 1498 IF_LESS_THAN_RETURN_FALSE(space_left, credential.size) 1499 memcpy(in, credential.buffer, credential.size); 1500 Update(credential.size, &in, &total_size, &space_left); 1501 1502 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)) 1503 ChangeEndian16((uint16_t*)&objectName.size, (uint16_t*)in); 1504 Update(sizeof(uint16_t), &in, &total_size, &space_left); 1505 1506 IF_LESS_THAN_RETURN_FALSE(space_left, objectName.size) 1507 memcpy(in, objectName.name, objectName.size); 1508 Update(objectName.size, &in, &total_size, &space_left); 1509 1510 int in_size = Tpm2_SetCommand(TPM_ST_NO_SESSIONS, TPM_CC_MakeCredential, 1511 commandBuf, total_size, params); 1512 printCommand("MakeCredential", in_size, commandBuf); 1513 if (!tpm.SendCommand(in_size, commandBuf)) { 1514 printf("SendCommand failed\n"); 1515 return false; 1516 } 1517 if (!tpm.GetResponse(&resp_size, resp_buf)) { 1518 printf("GetResponse failed\n"); 1519 return false; 1520 } 1521 uint16_t cap = 0; 1522 uint32_t responseSize; 1523 uint32_t responseCode; 1524 Tpm2_InterpretResponse(resp_size, resp_buf, &cap, 1525 &responseSize, &responseCode); 1526 printResponse("MakeCredential", cap, responseSize, responseCode, resp_buf); 1527 if (responseCode != TPM_RC_SUCCESS) 1528 return false; 1529 1530 byte* out = resp_buf + sizeof(TPM_RESPONSE); 1531 1532 ChangeEndian16((uint16_t*)out, (uint16_t*)&credentialBlob->size); 1533 out += sizeof(uint16_t); 1534 memcpy(credentialBlob->credential, out, credentialBlob->size); 1535 out += credentialBlob->size; 1536 1537 ChangeEndian16((uint16_t*)out, (uint16_t*)&secret->size); 1538 out += sizeof(uint16_t); 1539 memcpy(secret->secret, out, secret->size); 1540 out += secret->size; 1541 return true; 1542 } 1543 1544 bool Tpm2_ActivateCredential(LocalTpm& tpm, TPM_HANDLE activeHandle, 1545 TPM_HANDLE keyHandle, 1546 string& activeAuth, string& keyAuth, 1547 TPM2B_ID_OBJECT& credentialBlob, 1548 TPM2B_ENCRYPTED_SECRET& secret, 1549 TPM2B_DIGEST* certInfo) { 1550 byte commandBuf[2*MAX_SIZE_PARAMS]; 1551 int resp_size = MAX_SIZE_PARAMS; 1552 byte resp_buf[MAX_SIZE_PARAMS]; 1553 byte params[MAX_SIZE_PARAMS]; 1554 byte* in = params; 1555 int total_size = 0; 1556 int space_left = MAX_SIZE_PARAMS; 1557 1558 memset(params, 0, MAX_SIZE_PARAMS); 1559 memset(resp_buf, 0, MAX_SIZE_PARAMS); 1560 1561 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint32_t)) 1562 ChangeEndian32((uint32_t*)&activeHandle, (uint32_t*)in); 1563 Update(sizeof(uint32_t), &in, &total_size, &space_left); 1564 1565 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint32_t)) 1566 ChangeEndian32((uint32_t*)&keyHandle, (uint32_t*)in); 1567 Update(sizeof(uint32_t), &in, &total_size, &space_left); 1568 1569 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)) 1570 memset(in, 0, sizeof(uint16_t)); 1571 Update(sizeof(uint16_t), &in, &total_size, &space_left); 1572 1573 // twin auth areas 1574 byte activeAuthArea[512]; 1575 byte keyAuthArea[512]; 1576 byte outAuthArea[512]; 1577 int n = CreatePasswordAuthArea(activeAuth, 512, activeAuthArea); 1578 int m = CreatePasswordAuthArea(keyAuth, 512, keyAuthArea); 1579 uint16_t k = m + n - 4; 1580 ChangeEndian16(&k, (uint16_t*)outAuthArea); 1581 memcpy(&outAuthArea[2], &activeAuthArea[2], n - 2); 1582 memcpy(&outAuthArea[n], &keyAuthArea[2], m - 2); 1583 memcpy(in, outAuthArea, k + 2); 1584 Update(k + 2, &in, &total_size, &space_left); 1585 1586 ChangeEndian16((uint16_t*)&credentialBlob.size, (uint16_t*) in); 1587 Update(sizeof(uint16_t), &in, &total_size, &space_left); 1588 memcpy(in, credentialBlob.credential, credentialBlob.size); 1589 Update(credentialBlob.size, &in, &total_size, &space_left); 1590 1591 ChangeEndian16((uint16_t*)&secret.size, (uint16_t*) in); 1592 Update(sizeof(uint16_t), &in, &total_size, &space_left); 1593 memcpy(in, secret.secret, secret.size); 1594 Update(secret.size, &in, &total_size, &space_left); 1595 1596 int in_size = Tpm2_SetCommand(TPM_ST_SESSIONS, TPM_CC_ActivateCredential, 1597 commandBuf, total_size, params); 1598 printCommand("ActivateCredential", in_size, commandBuf); 1599 if (!tpm.SendCommand(in_size, commandBuf)) { 1600 printf("SendCommand failed\n"); 1601 return false; 1602 } 1603 if (!tpm.GetResponse(&resp_size, resp_buf)) { 1604 printf("GetResponse failed\n"); 1605 return false; 1606 } 1607 uint16_t cap = 0; 1608 uint32_t responseSize; 1609 uint32_t responseCode; 1610 Tpm2_InterpretResponse(resp_size, resp_buf, &cap, 1611 &responseSize, &responseCode); 1612 printResponse("ActivateCredential", cap, responseSize, responseCode, resp_buf); 1613 if (responseCode != TPM_RC_SUCCESS) 1614 return false; 1615 1616 byte* out = resp_buf + sizeof(TPM_RESPONSE); 1617 out += sizeof(uint32_t); 1618 ChangeEndian16((uint16_t*)out, (uint16_t*)&certInfo->size); 1619 out += sizeof(uint16_t); 1620 memcpy(certInfo->buffer, out, certInfo->size); 1621 out += certInfo->size; 1622 return true; 1623 } 1624 1625 bool Tpm2_Load(LocalTpm& tpm, TPM_HANDLE parent_handle, 1626 string& parentAuth, 1627 int size_public, byte* inPublic, 1628 int size_private, byte* inPrivate, 1629 TPM_HANDLE* new_handle, TPM2B_NAME* name) { 1630 byte commandBuf[2*MAX_SIZE_PARAMS]; 1631 memset(commandBuf, 0, 2*MAX_SIZE_PARAMS); 1632 1633 byte params_buf[MAX_SIZE_PARAMS]; 1634 memset(params_buf, 0, MAX_SIZE_PARAMS); 1635 byte* in = params_buf; 1636 int size_params = 0; 1637 int space_left = MAX_SIZE_PARAMS; 1638 int n; 1639 1640 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint32_t)) 1641 ChangeEndian32((uint32_t*)&parent_handle, (uint32_t*)in); 1642 Update(sizeof(uint32_t), &in, &size_params, &space_left); 1643 1644 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)) 1645 memset(in, 0, 2); 1646 Update(sizeof(uint16_t), &in, &size_params, &space_left); 1647 1648 n = CreatePasswordAuthArea(parentAuth, MAX_SIZE_PARAMS, in); 1649 IF_NEG_RETURN_FALSE(n) 1650 Update(n, &in, &size_params, &space_left); 1651 1652 IF_LESS_THAN_RETURN_FALSE(space_left, size_private + 2) 1653 memcpy(in, inPrivate, size_private + 2); 1654 Update(size_private + 2, &in, &size_params, &space_left); 1655 1656 IF_LESS_THAN_RETURN_FALSE(space_left, size_public + 2) 1657 memcpy(in, inPublic, size_public + 2); 1658 Update(size_public + 2, &in, &size_params, &space_left); 1659 1660 int in_size = Tpm2_SetCommand(TPM_ST_SESSIONS, TPM_CC_Load, (byte*)commandBuf, 1661 size_params, (byte*)params_buf); 1662 printCommand("Load", in_size, commandBuf); 1663 if (!tpm.SendCommand(in_size, (byte*)commandBuf)) { 1664 printf("SendCommand failed\n"); 1665 return false; 1666 } 1667 1668 int resp_size = MAX_SIZE_PARAMS; 1669 byte resp_buf[MAX_SIZE_PARAMS]; 1670 memset(resp_buf, 0, resp_size); 1671 if (!tpm.GetResponse(&resp_size, resp_buf)) { 1672 printf("GetResponse failed\n"); 1673 return false; 1674 } 1675 1676 uint16_t cap; 1677 uint32_t responseSize; 1678 uint32_t responseCode; 1679 Tpm2_InterpretResponse(resp_size, resp_buf, &cap, 1680 &responseSize, &responseCode); 1681 printResponse("Load", cap, responseSize, responseCode, resp_buf); 1682 if (responseCode != TPM_RC_SUCCESS) 1683 return false; 1684 return GetLoadOut(responseSize - sizeof(TPM_RESPONSE), 1685 &resp_buf[sizeof(TPM_RESPONSE)], new_handle, name); 1686 } 1687 1688 bool Tpm2_Save(LocalTpm& tpm) { 1689 printf("Unimplmented\n"); 1690 return false; 1691 } 1692 1693 int GetName(uint16_t size_in, byte* in, TPM2B_NAME* name) { 1694 int total_size = 0; 1695 1696 ChangeEndian16((uint16_t*) in, (uint16_t*)&name->size); 1697 in += sizeof(uint16_t); 1698 memcpy(name->name, in, name->size); 1699 in += name->size; 1700 return total_size; 1701 } 1702 1703 int GetRsaParams(uint16_t size_in, byte* input, TPMS_RSA_PARMS& rsaParams, 1704 TPM2B_PUBLIC_KEY_RSA* rsa) { 1705 int total_size = 0; 1706 1707 ChangeEndian16((uint16_t*) input, (uint16_t*)&rsaParams.symmetric.algorithm); 1708 input += sizeof(uint16_t); 1709 total_size += sizeof(uint16_t); 1710 if (rsaParams.symmetric.algorithm != TPM_ALG_NULL) { 1711 ChangeEndian16((uint16_t*) input, (uint16_t*)&rsaParams.symmetric.keyBits); 1712 input += sizeof(uint16_t); 1713 total_size += sizeof(uint16_t); 1714 ChangeEndian16((uint16_t*) input, (uint16_t*)&rsaParams.symmetric.mode); 1715 input += sizeof(uint16_t); 1716 total_size += sizeof(uint16_t); 1717 ChangeEndian16((uint16_t*) input, 1718 (uint16_t*)&rsaParams.scheme.scheme); 1719 input += sizeof(uint16_t); 1720 total_size += sizeof(uint16_t); 1721 // TODO(jlm): what goes here? Details? 1722 input += sizeof(uint16_t); 1723 total_size += sizeof(uint16_t); 1724 } else { 1725 ChangeEndian16((uint16_t*) input, 1726 (uint16_t*)&rsaParams.scheme.scheme); 1727 input += sizeof(uint16_t); 1728 total_size += sizeof(uint16_t); 1729 // TODO(jlm): what goes here? Details? 1730 input += sizeof(uint32_t); 1731 total_size += sizeof(uint32_t); 1732 } 1733 // Exponent 1734 ChangeEndian32((uint32_t*) input, (uint32_t*)&rsaParams.exponent); 1735 input += sizeof(uint32_t); 1736 total_size += sizeof(uint32_t); 1737 // modulus size 1738 ChangeEndian16((uint16_t*) input, (uint16_t*)&rsa->size); 1739 input += sizeof(uint16_t); 1740 total_size += sizeof(uint16_t); 1741 // modulus 1742 memcpy(rsa->buffer, input, rsa->size); 1743 input += rsa->size; 1744 total_size += rsa->size; 1745 return total_size; 1746 } 1747 1748 bool GetReadPublicOut(uint16_t size_in, byte* input, TPM2B_PUBLIC* outPublic) { 1749 ChangeEndian16((uint16_t*) input, (uint16_t*)&outPublic->publicArea.type); 1750 input += sizeof(uint16_t); 1751 size_in -= sizeof(uint16_t); 1752 ChangeEndian16((uint16_t*) input, (uint16_t*)&outPublic->publicArea.nameAlg); 1753 input += sizeof(uint16_t); 1754 size_in -= sizeof(uint16_t); 1755 ChangeEndian32((uint32_t*) input, 1756 (uint32_t*)&outPublic->publicArea.objectAttributes); 1757 input += sizeof(uint32_t); 1758 size_in -= sizeof(uint32_t); 1759 ChangeEndian16((uint16_t*) input, 1760 (uint16_t*)&outPublic->publicArea.authPolicy.size); 1761 input += sizeof(uint16_t); 1762 size_in -= sizeof(uint16_t); 1763 memcpy(outPublic->publicArea.authPolicy.buffer, input, 1764 outPublic->publicArea.authPolicy.size); 1765 input += outPublic->publicArea.authPolicy.size; 1766 size_in -= outPublic->publicArea.authPolicy.size; 1767 1768 if (outPublic->publicArea.type!= TPM_ALG_RSA) { 1769 printf("Can only retrieve RSA Params %04x\n", outPublic->publicArea.nameAlg); 1770 return false; 1771 } 1772 int n = GetRsaParams(size_in, input, 1773 outPublic->publicArea.parameters.rsaDetail, 1774 &outPublic->publicArea.unique.rsa); 1775 if (n < 0) { 1776 printf("Can't get RSA Params\n"); 1777 return false; 1778 } 1779 input += n; 1780 return true; 1781 } 1782 1783 bool Tpm2_ReadPublic(LocalTpm& tpm, TPM_HANDLE handle, 1784 uint16_t* pub_blob_size, byte* pub_blob, 1785 TPM2B_PUBLIC* outPublic, TPM2B_NAME* name, 1786 TPM2B_NAME* qualifiedName) { 1787 byte commandBuf[2*MAX_SIZE_PARAMS]; 1788 memset(commandBuf, 0, MAX_SIZE_PARAMS); 1789 1790 int size_resp = MAX_SIZE_PARAMS; 1791 byte resp_buf[MAX_SIZE_PARAMS]; 1792 int size_params = 0; 1793 byte params_buf[MAX_SIZE_PARAMS]; 1794 byte* in = params_buf; 1795 int space_left = MAX_SIZE_PARAMS; 1796 int n; 1797 1798 memset(resp_buf, 0, MAX_SIZE_PARAMS); 1799 memset(params_buf, 0, MAX_SIZE_PARAMS); 1800 1801 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint32_t)) 1802 ChangeEndian32((uint32_t*)&handle, (uint32_t*)in); 1803 Update(sizeof(uint32_t), &in, &size_params, &space_left); 1804 1805 int in_size = Tpm2_SetCommand(TPM_ST_NO_SESSIONS, TPM_CC_ReadPublic, 1806 commandBuf, size_params, params_buf); 1807 printCommand("ReadPublic", in_size, commandBuf); 1808 if (!tpm.SendCommand(in_size, commandBuf)) { 1809 printf("SendCommand failed\n"); 1810 return false; 1811 } 1812 if (!tpm.GetResponse(&size_resp, resp_buf)) { 1813 printf("GetResponse failed\n"); 1814 return false; 1815 } 1816 uint16_t cap = 0; 1817 uint32_t responseSize; 1818 uint32_t responseCode; 1819 Tpm2_InterpretResponse(size_resp, resp_buf, &cap, 1820 &responseSize, &responseCode); 1821 printResponse("ReadPublic", cap, responseSize, responseCode, resp_buf); 1822 if (responseCode != TPM_RC_SUCCESS) 1823 return false; 1824 byte* out = resp_buf + sizeof(TPM_RESPONSE); 1825 1826 ChangeEndian16((uint16_t*)out, (uint16_t*)&outPublic->size); 1827 *pub_blob_size = outPublic->size + 2; 1828 memcpy(pub_blob, out, outPublic->size + 2); 1829 out += sizeof(uint16_t); 1830 if (!GetReadPublicOut(outPublic->size, out, outPublic)) { 1831 printf("ReadPublic can't GetPublic\n"); 1832 return false; 1833 } 1834 out += outPublic->size; 1835 n = GetName(0, out, name); 1836 if (n < 0) { 1837 printf("ReadPublic can't Get name\n"); 1838 return false; 1839 } 1840 out += n; 1841 n = GetName(0, out, qualifiedName); 1842 if (n < 0) { 1843 printf("ReadPublic can't Get qualified name\n"); 1844 return false; 1845 } 1846 out += n; 1847 return true; 1848 } 1849 1850 bool Tpm2_Certify(LocalTpm& tpm, TPM_HANDLE signedKey, TPM_HANDLE signingKey, 1851 string& auth_signed_key, string& auth_signing_key, 1852 TPM2B_DATA& qualifyingData, 1853 TPM2B_ATTEST* attest, TPMT_SIGNATURE* sig) { 1854 byte commandBuf[2*MAX_SIZE_PARAMS]; 1855 1856 int size_resp = MAX_SIZE_PARAMS; 1857 byte resp_buf[MAX_SIZE_PARAMS]; 1858 memset(resp_buf, 0, MAX_SIZE_PARAMS); 1859 int size_params = 0; 1860 byte params_buf[MAX_SIZE_PARAMS]; 1861 int space_left = MAX_SIZE_PARAMS; 1862 byte* in = params_buf; 1863 int n; 1864 1865 memset(commandBuf, 0, MAX_SIZE_PARAMS); 1866 memset(params_buf, 0, MAX_SIZE_PARAMS); 1867 1868 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint32_t)) 1869 ChangeEndian32((uint32_t*)&signedKey, (uint32_t*)in); 1870 Update(sizeof(uint32_t), &in, &size_params, &space_left); 1871 1872 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint32_t)) 1873 ChangeEndian32((uint32_t*)&signingKey, (uint32_t*)in); 1874 Update(sizeof(uint32_t), &in, &size_params, &space_left); 1875 1876 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)) 1877 memset(in, 0, sizeof(uint16_t)); 1878 Update(sizeof(uint16_t), &in, &size_params, &space_left); 1879 1880 byte* size_ptr = in; 1881 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)) 1882 memset(in, 0, sizeof(uint16_t)); 1883 Update(sizeof(uint16_t), &in, &size_params, &space_left); 1884 1885 uint16_t first_position= size_params; 1886 uint32_t password_auth = TPM_RS_PW; 1887 1888 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint32_t)) 1889 ChangeEndian32((uint32_t*)&password_auth, (uint32_t*)in); 1890 Update(sizeof(uint32_t), &in, &size_params, &space_left); 1891 1892 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)) 1893 memset(in, 0, sizeof(uint16_t)); 1894 Update(sizeof(uint16_t), &in, &size_params, &space_left); 1895 1896 IF_LESS_THAN_RETURN_FALSE(space_left, 1) 1897 *in = 1; 1898 Update(1, &in, &size_params, &space_left); 1899 1900 n = SetPasswordData(auth_signed_key, space_left, in); 1901 IF_NEG_RETURN_FALSE(n); 1902 Update(n, &in, &size_params, &space_left); 1903 1904 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint32_t)) 1905 ChangeEndian32((uint32_t*)&password_auth, (uint32_t*)in); 1906 Update(sizeof(uint32_t), &in, &size_params, &space_left); 1907 1908 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)) 1909 memset(in, 0, sizeof(uint16_t)); 1910 Update(sizeof(uint16_t), &in, &size_params, &space_left); 1911 1912 IF_LESS_THAN_RETURN_FALSE(space_left, 1) 1913 *in = 1; 1914 Update(1, &in, &size_params, &space_left); 1915 1916 n = SetPasswordData(auth_signed_key, space_left, in); 1917 IF_NEG_RETURN_FALSE(n); 1918 Update(n, &in, &size_params, &space_left); 1919 1920 uint16_t block_size = size_params - first_position; 1921 ChangeEndian16((uint16_t*)&block_size, (uint16_t*)size_ptr); 1922 1923 // parameters: qualifying data, scheme 1924 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)) 1925 ChangeEndian16((uint16_t*)&qualifyingData.size, (uint16_t*)in); 1926 Update(sizeof(uint16_t), &in, &size_params, &space_left); 1927 1928 IF_LESS_THAN_RETURN_FALSE(space_left, qualifyingData.size) 1929 memcpy(in, qualifyingData.buffer, qualifyingData.size); 1930 Update(qualifyingData.size, &in, &size_params, &space_left); 1931 1932 TPMI_ALG_HASH alg = TPM_ALG_NULL; 1933 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)) 1934 ChangeEndian16((uint16_t*)&alg, (uint16_t*)in); 1935 Update(sizeof(uint16_t), &in, &size_params, &space_left); 1936 int in_size = Tpm2_SetCommand(TPM_ST_SESSIONS, TPM_CC_Certify, 1937 commandBuf, size_params, params_buf); 1938 printCommand("Certify", in_size, commandBuf); 1939 if (!tpm.SendCommand(in_size, commandBuf)) { 1940 printf("SendCommand failed\n"); 1941 return false; 1942 } 1943 if (!tpm.GetResponse(&size_resp, resp_buf)) { 1944 printf("GetResponse failed\n"); 1945 return false; 1946 } 1947 uint16_t cap = 0; 1948 uint32_t responseSize; 1949 uint32_t responseCode; 1950 Tpm2_InterpretResponse(size_resp, resp_buf, &cap, 1951 &responseSize, &responseCode); 1952 printResponse("Certify", cap, responseSize, responseCode, resp_buf); 1953 if (responseCode != TPM_RC_SUCCESS) 1954 return false; 1955 byte* out = resp_buf + sizeof(TPM_RESPONSE); 1956 out += 2*sizeof(uint16_t); // check this 1957 ChangeEndian16((uint16_t*)out, &attest->size); 1958 out += sizeof(uint16_t); 1959 memcpy(attest->attestationData, out, attest->size); 1960 out += attest->size; 1961 ChangeEndian16((uint16_t*)out, &sig->sigAlg); 1962 out += sizeof(uint16_t); 1963 if (sig->sigAlg != TPM_ALG_RSASSA) { 1964 printf("I only understand TPM_ALG_RSASSA signatures for now\n"); 1965 return false; 1966 } 1967 ChangeEndian16((uint16_t*)out, &sig->signature.rsassa.hash); 1968 out += sizeof(uint16_t); 1969 ChangeEndian16((uint16_t*)out, &sig->signature.rsassa.sig.size); 1970 out += sizeof(uint16_t); 1971 memcpy(sig->signature.rsassa.sig.buffer, out, 1972 sig->signature.rsassa.sig.size); 1973 out += sizeof(sig->signature.rsassa.sig.size); 1974 return true; 1975 } 1976 1977 bool GetCreateOut(int size, byte* in, int* size_public, byte* out_public, 1978 int* size_private, byte* out_private, 1979 TPM2B_CREATION_DATA* creation_out, TPM2B_DIGEST* digest_out, 1980 TPMT_TK_CREATION* creation_ticket) { 1981 byte* current_in = in; 1982 1983 uint32_t unknown; 1984 ChangeEndian32((uint32_t*)current_in, (uint32_t*)&unknown); 1985 current_in += sizeof(uint32_t); 1986 1987 *size_private = 0; 1988 ChangeEndian16((uint16_t*)current_in, (uint16_t*)size_private); 1989 memcpy(out_private, current_in, *size_private + 2); 1990 current_in += *size_private + 2; 1991 1992 *size_public = 0; 1993 ChangeEndian16((uint16_t*)current_in, (uint16_t*)size_public); 1994 memcpy(out_public, current_in, *size_public + 2); 1995 current_in += *size_public + 2; 1996 1997 ChangeEndian16((uint16_t*)current_in, &creation_out->size); 1998 current_in += sizeof(uint16_t); 1999 ChangeEndian32((uint32_t*)current_in, 2000 &creation_out->creationData.pcrSelect.count); 2001 current_in += sizeof(uint32_t); 2002 2003 for (uint32_t i = 0; i < creation_out->creationData.pcrSelect.count; i++) { 2004 ChangeEndian16((uint16_t*)current_in, 2005 &creation_out->creationData.pcrSelect.pcrSelections[i].hash); 2006 current_in += sizeof(uint16_t); 2007 creation_out->creationData.pcrSelect.pcrSelections[i].sizeofSelect = 2008 *(current_in++); 2009 memcpy(&creation_out->creationData.pcrSelect.pcrSelections[i].pcrSelect, 2010 current_in, 2011 creation_out->creationData.pcrSelect.pcrSelections[i].sizeofSelect); 2012 current_in += 2013 creation_out->creationData.pcrSelect.pcrSelections[i].sizeofSelect; 2014 } 2015 2016 ChangeEndian16((uint16_t*)current_in, 2017 &creation_out->creationData.pcrDigest.size); 2018 current_in += sizeof(uint16_t); 2019 memcpy(creation_out->creationData.pcrDigest.buffer, current_in, 2020 creation_out->creationData.pcrDigest.size); 2021 current_in += creation_out->creationData.pcrDigest.size; 2022 return true; 2023 } 2024 2025 bool Tpm2_CreateKey(LocalTpm& tpm, TPM_HANDLE parent_handle, 2026 string& parentAuth, string& authString, 2027 TPML_PCR_SELECTION& pcr_selection, 2028 TPM_ALG_ID enc_alg, TPM_ALG_ID int_alg, 2029 TPMA_OBJECT& flags, TPM_ALG_ID sym_alg, 2030 TPMI_AES_KEY_BITS sym_key_size, 2031 TPMI_ALG_SYM_MODE sym_mode, TPM_ALG_ID sig_scheme, 2032 int mod_size, uint32_t exp, 2033 int* size_public, byte* out_public, 2034 int* size_private, byte* out_private, 2035 TPM2B_CREATION_DATA* creation_out, 2036 TPM2B_DIGEST* digest_out, TPMT_TK_CREATION* creation_ticket) { 2037 byte commandBuf[2*MAX_SIZE_PARAMS]; 2038 2039 byte params[MAX_SIZE_PARAMS]; 2040 byte* in = params; 2041 int size_params = 0; 2042 int space_left = MAX_SIZE_PARAMS; 2043 int n; 2044 2045 memset(commandBuf, 0, 2*MAX_SIZE_PARAMS); 2046 memset(params, 0, MAX_SIZE_PARAMS); 2047 2048 // parent handle 2049 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint32_t)) 2050 ChangeEndian32((uint32_t*) &parent_handle, (uint32_t*)in); 2051 Update(sizeof(uint32_t), &in, &size_params, &space_left); 2052 2053 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)) 2054 memset(in, 0, sizeof(uint16_t)); 2055 Update(sizeof(uint16_t), &in, &size_params, &space_left); 2056 2057 n = CreatePasswordAuthArea(authString, space_left, in); 2058 IF_NEG_RETURN_FALSE(n) 2059 Update(n, &in, &size_params, &space_left); 2060 2061 n = CreateSensitiveArea(authString, 0, NULL, space_left, in); 2062 IF_NEG_RETURN_FALSE(n) 2063 Update(n, &in, &size_params, &space_left); 2064 2065 TPM2B_PUBLIC pub_key; 2066 FillPublicRsaTemplate(enc_alg, int_alg, flags, sym_alg, 2067 sym_key_size, sym_mode, sig_scheme, 2068 mod_size, exp, pub_key); 2069 2070 n = Marshal_Public_Key_Info(pub_key, space_left, in); 2071 IF_NEG_RETURN_FALSE(n) 2072 Update(n, &in, &size_params, &space_left); 2073 2074 TPM2B_DATA data; 2075 FillEmptyData(data); 2076 n = Marshal_OutsideInfo(data, space_left, in); 2077 IF_NEG_RETURN_FALSE(n) 2078 Update(n, &in, &size_params, &space_left); 2079 2080 n = Marshal_PCR_Long_Selection(pcr_selection, space_left, in); 2081 IF_NEG_RETURN_FALSE(n) 2082 Update(n, &in, &size_params, &space_left); 2083 2084 int in_size = Tpm2_SetCommand(TPM_ST_SESSIONS, TPM_CC_Create, 2085 (byte*)commandBuf, 2086 size_params, 2087 (byte*)params); 2088 printCommand("Create", in_size, commandBuf); 2089 if (!tpm.SendCommand(in_size, (byte*)commandBuf)) { 2090 printf("SendCommand failed\n"); 2091 return false; 2092 } 2093 2094 int resp_size = MAX_SIZE_PARAMS; 2095 byte resp_buf[MAX_SIZE_PARAMS]; 2096 memset(resp_buf, 0, resp_size); 2097 if (!tpm.GetResponse(&resp_size, resp_buf)) { 2098 printf("GetResponse failed\n"); 2099 return false; 2100 } 2101 2102 uint16_t cap; 2103 uint32_t responseSize; 2104 uint32_t responseCode; 2105 Tpm2_InterpretResponse(resp_size, resp_buf, &cap, 2106 &responseSize, &responseCode); 2107 printResponse("Create", cap, responseSize, responseCode, resp_buf); 2108 if (responseCode != TPM_RC_SUCCESS) 2109 return false; 2110 2111 return GetCreateOut(responseSize - sizeof(TPM_RESPONSE), 2112 &resp_buf[sizeof(TPM_RESPONSE)], 2113 size_public, out_public, 2114 size_private, out_private, 2115 creation_out, digest_out, creation_ticket); 2116 } 2117 2118 bool Tpm2_CreateSealed(LocalTpm& tpm, TPM_HANDLE parent_handle, 2119 int size_policy_digest, byte* policy_digest, 2120 string& parentAuth, 2121 int size_to_seal, byte* to_seal, 2122 TPML_PCR_SELECTION& pcr_selection, 2123 TPM_ALG_ID int_alg, 2124 TPMA_OBJECT& flags, TPM_ALG_ID sym_alg, 2125 TPMI_AES_KEY_BITS sym_key_size, 2126 TPMI_ALG_SYM_MODE sym_mode, TPM_ALG_ID sig_scheme, 2127 int mod_size, uint32_t exp, 2128 int* size_public, byte* out_public, 2129 int* size_private, byte* out_private, 2130 TPM2B_CREATION_DATA* creation_out, 2131 TPM2B_DIGEST* digest_out, 2132 TPMT_TK_CREATION* creation_ticket) { 2133 byte commandBuf[2*MAX_SIZE_PARAMS]; 2134 2135 byte params[MAX_SIZE_PARAMS]; 2136 byte* in = params; 2137 int size_params = 0; 2138 int space_left = MAX_SIZE_PARAMS; 2139 int n; 2140 2141 memset(commandBuf, 0, 2*MAX_SIZE_PARAMS); 2142 memset(params, 0, MAX_SIZE_PARAMS); 2143 2144 // parent handle 2145 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint32_t)) 2146 ChangeEndian32((uint32_t*) &parent_handle, (uint32_t*)in); 2147 Update(sizeof(uint32_t), &in, &size_params, &space_left); 2148 2149 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)) 2150 memset(in, 0, sizeof(uint16_t)); 2151 Update(sizeof(uint16_t), &in, &size_params, &space_left); 2152 2153 string emptyAuth; 2154 n = CreatePasswordAuthArea(parentAuth, space_left, in); 2155 IF_NEG_RETURN_FALSE(n) 2156 Update(n, &in, &size_params, &space_left); 2157 n = CreateSensitiveArea(parentAuth, size_to_seal, to_seal, 2158 space_left, in); 2159 IF_NEG_RETURN_FALSE(n) 2160 Update(n, &in, &size_params, &space_left); 2161 2162 TPM2B_PUBLIC keyed_hash; 2163 FillKeyedHashTemplate(TPM_ALG_KEYEDHASH, int_alg, flags, 2164 size_policy_digest, policy_digest, keyed_hash); 2165 n = Marshal_Keyed_Hash_Info(keyed_hash, space_left, in); 2166 IF_NEG_RETURN_FALSE(n) 2167 Update(n, &in, &size_params, &space_left); 2168 2169 TPM2B_DATA data; 2170 FillEmptyData(data); 2171 n = Marshal_OutsideInfo(data, space_left, in); 2172 IF_NEG_RETURN_FALSE(n) 2173 Update(n, &in, &size_params, &space_left); 2174 2175 n = Marshal_PCR_Long_Selection(pcr_selection, space_left, in); 2176 IF_NEG_RETURN_FALSE(n) 2177 Update(n, &in, &size_params, &space_left); 2178 2179 int in_size = Tpm2_SetCommand(TPM_ST_SESSIONS, TPM_CC_Create, 2180 (byte*)commandBuf, 2181 size_params, 2182 (byte*)params); 2183 printCommand("CreateSealed", in_size, commandBuf); 2184 if (!tpm.SendCommand(in_size, (byte*)commandBuf)) { 2185 printf("SendCommand failed\n"); 2186 return false; 2187 } 2188 2189 int resp_size = MAX_SIZE_PARAMS; 2190 byte resp_buf[MAX_SIZE_PARAMS]; 2191 memset(resp_buf, 0, resp_size); 2192 if (!tpm.GetResponse(&resp_size, resp_buf)) { 2193 printf("GetResponse failed\n"); 2194 return false; 2195 } 2196 2197 uint16_t cap; 2198 uint32_t responseSize; 2199 uint32_t responseCode; 2200 Tpm2_InterpretResponse(resp_size, resp_buf, &cap, 2201 &responseSize, &responseCode); 2202 printResponse("Create", cap, responseSize, responseCode, resp_buf); 2203 if (responseCode != TPM_RC_SUCCESS) 2204 return false; 2205 2206 return GetCreateOut(responseSize - sizeof(TPM_RESPONSE), 2207 &resp_buf[sizeof(TPM_RESPONSE)], 2208 size_public, out_public, size_private, out_private, 2209 creation_out, digest_out, creation_ticket); 2210 } 2211 2212 bool ComputeHmac(int size_buf, byte* command, TPM2B_NONCE& newNonce, 2213 TPM2B_NONCE& oldNonce, uint16_t* size_hmac, 2214 byte* hmac) { 2215 memset(hmac, 0 , *size_hmac); 2216 *size_hmac = 0; 2217 return true; 2218 } 2219 2220 bool Tpm2_Unseal(LocalTpm& tpm, TPM_HANDLE item_handle, string& parentAuth, 2221 TPM_HANDLE session_handle, TPM2B_NONCE& nonce, 2222 byte session_attributes, TPM2B_DIGEST& hmac_digest, 2223 int* out_size, byte* unsealed) { 2224 byte commandBuf[2*MAX_SIZE_PARAMS]; 2225 memset(commandBuf, 0, 2*MAX_SIZE_PARAMS); 2226 2227 int size_resp = MAX_SIZE_PARAMS; 2228 byte resp_buf[MAX_SIZE_PARAMS]; 2229 int size_params = 0; 2230 int space_left = MAX_SIZE_PARAMS; 2231 byte params_buf[MAX_SIZE_PARAMS]; 2232 byte* in = params_buf; 2233 int n; 2234 2235 memset(params_buf, 0, MAX_SIZE_PARAMS); 2236 memset(resp_buf, 0, MAX_SIZE_PARAMS); 2237 2238 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint32_t)) 2239 ChangeEndian32((uint32_t*)&item_handle, (uint32_t*)in); 2240 Update(sizeof(uint32_t), &in, &size_params, &space_left); 2241 2242 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)) 2243 memset(in, 0, sizeof(uint16_t)); 2244 Update(sizeof(uint16_t), &in, &size_params, &space_left); 2245 2246 byte* auth_area_size_ptr = in; 2247 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)) 2248 memset(in, 0, sizeof(uint16_t)); 2249 Update(sizeof(uint16_t), &in, &size_params, &space_left); 2250 2251 uint16_t start_of_auth_area = size_params; 2252 2253 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint32_t)) 2254 ChangeEndian32((uint32_t*)&session_handle, (uint32_t*)in); 2255 Update(sizeof(uint32_t), &in, &size_params, &space_left); 2256 2257 // null hmac 2258 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)) 2259 memset(in, 0, sizeof(uint16_t)); 2260 Update(sizeof(uint16_t), &in, &size_params, &space_left); 2261 2262 IF_LESS_THAN_RETURN_FALSE(space_left, 1) 2263 *in = session_attributes; 2264 Update(1, &in, &size_params, &space_left); 2265 2266 // password 2267 n = SetPasswordData(parentAuth, space_left, in); 2268 IF_NEG_RETURN_FALSE(n) 2269 Update(n, &in, &size_params, &space_left); 2270 2271 uint16_t auth_area = size_params - start_of_auth_area; 2272 ChangeEndian16(&auth_area, (uint16_t*)auth_area_size_ptr); 2273 int in_size = Tpm2_SetCommand(TPM_ST_SESSIONS, TPM_CC_Unseal, 2274 commandBuf, size_params, params_buf); 2275 printCommand("Unseal", in_size, commandBuf); 2276 if (!tpm.SendCommand(in_size, commandBuf)) { 2277 printf("SendCommand failed\n"); 2278 return false; 2279 } 2280 if (!tpm.GetResponse(&size_resp, resp_buf)) { 2281 printf("GetResponse failed\n"); 2282 return false; 2283 } 2284 uint16_t cap = 0; 2285 uint32_t responseSize; 2286 uint32_t responseCode; 2287 Tpm2_InterpretResponse(size_resp, resp_buf, &cap, 2288 &responseSize, &responseCode); 2289 printResponse("Unseal", cap, responseSize, responseCode, resp_buf); 2290 if (responseCode != TPM_RC_SUCCESS) 2291 return false; 2292 *out_size = (int)(responseSize - sizeof(TPM_RESPONSE)); 2293 memcpy(unsealed, resp_buf + sizeof(TPM_RESPONSE), *out_size); 2294 return true; 2295 } 2296 2297 bool Tpm2_Quote(LocalTpm& tpm, TPM_HANDLE signingHandle, string& parentAuth, 2298 int quote_size, byte* toQuote, 2299 TPMT_SIG_SCHEME scheme, TPML_PCR_SELECTION& pcr_selection, 2300 TPM_ALG_ID sig_alg, TPM_ALG_ID hash_alg, 2301 int* attest_size, byte* attest, int* sig_size, byte* sig) { 2302 byte commandBuf[2*MAX_SIZE_PARAMS]; 2303 memset(commandBuf, 0, 2*MAX_SIZE_PARAMS); 2304 2305 int size_resp = MAX_SIZE_PARAMS; 2306 byte resp_buf[MAX_SIZE_PARAMS]; 2307 int size_params = 0; 2308 int space_left = MAX_SIZE_PARAMS; 2309 byte params_buf[MAX_SIZE_PARAMS]; 2310 byte* in = params_buf; 2311 int n; 2312 2313 memset(resp_buf, 0, MAX_SIZE_PARAMS); 2314 memset(params_buf, 0, MAX_SIZE_PARAMS); 2315 2316 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint32_t)) 2317 ChangeEndian32((uint32_t*)&signingHandle, (uint32_t*)in); 2318 Update(sizeof(uint32_t), &in, &size_params, &space_left); 2319 2320 FillSignatureSchemeTemplate(sig_alg, hash_alg, scheme); 2321 2322 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)) 2323 memset(in, 0, sizeof(uint16_t)); 2324 Update(sizeof(uint16_t), &in, &size_params, &space_left); 2325 2326 n = CreatePasswordAuthArea(parentAuth, space_left, in); 2327 IF_NEG_RETURN_FALSE(n); 2328 Update(n, &in, &size_params, &space_left); 2329 2330 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)) 2331 ChangeEndian16((uint16_t*)"e_size, (uint16_t*)in); 2332 Update(sizeof(uint16_t), &in, &size_params, &space_left); 2333 2334 IF_LESS_THAN_RETURN_FALSE(space_left, quote_size) 2335 memcpy(in, toQuote, quote_size); 2336 Update(quote_size, &in, &size_params, &space_left); 2337 2338 uint16_t algorithm = TPM_ALG_NULL; 2339 IF_LESS_THAN_RETURN_FALSE(space_left, quote_size) 2340 ChangeEndian16((uint16_t*)&algorithm, (uint16_t*)in); 2341 Update(sizeof(uint16_t), &in, &size_params, &space_left); 2342 2343 ChangeEndian16((uint16_t*)&algorithm, (uint16_t*)in); 2344 memset(in, 0, sizeof(uint16_t)); 2345 Update(sizeof(uint16_t), &in, &size_params, &space_left); 2346 2347 n= Marshal_Signature_Scheme_Info(scheme, space_left, in); 2348 IF_NEG_RETURN_FALSE(n); 2349 Update(n, &in, &size_params, &space_left); 2350 2351 n = Marshal_PCR_Short_Selection(pcr_selection.pcrSelections[0], space_left, in); 2352 IF_NEG_RETURN_FALSE(n); 2353 Update(n, &in, &size_params, &space_left); 2354 2355 int in_size = Tpm2_SetCommand(TPM_ST_SESSIONS, TPM_CC_Quote, 2356 commandBuf, size_params, params_buf); 2357 printCommand("Quote", in_size, commandBuf); 2358 if (!tpm.SendCommand(in_size, commandBuf)) { 2359 printf("SendCommand failed\n"); 2360 return false; 2361 } 2362 if (!tpm.GetResponse(&size_resp, resp_buf)) { 2363 printf("GetResponse failed\n"); 2364 return false; 2365 } 2366 uint16_t cap = 0; 2367 uint32_t responseSize; 2368 uint32_t responseCode; 2369 Tpm2_InterpretResponse(size_resp, resp_buf, &cap, 2370 &responseSize, &responseCode); 2371 printResponse("Quote", cap, responseSize, responseCode, resp_buf); 2372 if (responseCode != TPM_RC_SUCCESS) 2373 return false; 2374 2375 byte* out = &resp_buf[sizeof(TPM_RESPONSE)]; 2376 TPMI_ALG_SIG_SCHEME scheme1; 2377 TPMI_ALG_SIG_SCHEME scheme2; 2378 2379 out += sizeof(uint32_t); 2380 ChangeEndian16((uint16_t*)out, (uint16_t*)attest_size); 2381 out += sizeof(uint16_t); 2382 memcpy(attest, out, *attest_size); 2383 out += *attest_size; 2384 ChangeEndian16((uint16_t*)out, (uint16_t*)&scheme1); 2385 out += sizeof(uint16_t); 2386 ChangeEndian16((uint16_t*)out, (uint16_t*)&scheme2); 2387 out += sizeof(uint16_t); 2388 ChangeEndian16((uint16_t*)out, (uint16_t*)sig_size); 2389 out += sizeof(uint16_t); 2390 memcpy(sig, out, *sig_size); 2391 out += *sig_size; 2392 return true; 2393 } 2394 2395 bool Tpm2_LoadContext(LocalTpm& tpm, uint16_t size, byte* saveArea, 2396 TPM_HANDLE* handle) { 2397 byte commandBuf[2*MAX_SIZE_PARAMS]; 2398 memset(commandBuf, 0, 2*MAX_SIZE_PARAMS); 2399 2400 int size_resp = MAX_SIZE_PARAMS; 2401 byte resp_buf[MAX_SIZE_PARAMS]; 2402 memset(resp_buf, 0, MAX_SIZE_PARAMS); 2403 int size_params = 0; 2404 byte params_buf[MAX_SIZE_PARAMS]; 2405 memset(params_buf, 0, MAX_SIZE_PARAMS); 2406 byte* current_out = params_buf; 2407 2408 memcpy(current_out, saveArea, size); 2409 size_params += size; 2410 current_out += size; 2411 2412 int in_size = Tpm2_SetCommand(TPM_ST_NO_SESSIONS, TPM_CC_ContextLoad, 2413 commandBuf, size_params, params_buf); 2414 printCommand("ContextLoad", in_size, commandBuf); 2415 if (!tpm.SendCommand(in_size, commandBuf)) { 2416 printf("SendCommand failed\n"); 2417 return false; 2418 } 2419 if (!tpm.GetResponse(&size_resp, resp_buf)) { 2420 printf("GetResponse failed\n"); 2421 return false; 2422 } 2423 uint16_t cap = 0; 2424 uint32_t responseSize; 2425 uint32_t responseCode; 2426 Tpm2_InterpretResponse(size_resp, resp_buf, &cap, 2427 &responseSize, &responseCode); 2428 printResponse("ContextLoad", cap, responseSize, responseCode, resp_buf); 2429 if (responseCode != TPM_RC_SUCCESS) 2430 return false; 2431 ChangeEndian32((uint32_t*)(resp_buf + responseSize - sizeof(uint32_t)), 2432 (uint32_t*)handle); 2433 return true; 2434 } 2435 2436 bool Tpm2_SaveContext(LocalTpm& tpm, TPM_HANDLE handle, uint16_t* size, 2437 byte* saveArea) { 2438 byte commandBuf[2*MAX_SIZE_PARAMS]; 2439 memset(commandBuf, 0, 2*MAX_SIZE_PARAMS); 2440 2441 int size_resp = MAX_SIZE_PARAMS; 2442 byte resp_buf[MAX_SIZE_PARAMS]; 2443 memset(resp_buf, 0, MAX_SIZE_PARAMS); 2444 int size_params = 0; 2445 byte params_buf[MAX_SIZE_PARAMS]; 2446 memset(params_buf, 0, MAX_SIZE_PARAMS); 2447 byte* current_out = params_buf; 2448 2449 ChangeEndian32((uint32_t*)&handle, (uint32_t*)current_out); 2450 size_params += sizeof(uint32_t); 2451 current_out += sizeof(uint32_t); 2452 2453 int in_size = Tpm2_SetCommand(TPM_ST_NO_SESSIONS, TPM_CC_ContextSave, 2454 commandBuf, size_params, params_buf); 2455 printCommand("SaveContext", in_size, commandBuf); 2456 if (!tpm.SendCommand(in_size, commandBuf)) { 2457 printf("SendCommand failed\n"); 2458 return false; 2459 } 2460 if (!tpm.GetResponse(&size_resp, resp_buf)) { 2461 printf("GetResponse failed\n"); 2462 return false; 2463 } 2464 uint16_t cap = 0; 2465 uint32_t responseSize; 2466 uint32_t responseCode; 2467 Tpm2_InterpretResponse(size_resp, resp_buf, &cap, 2468 &responseSize, &responseCode); 2469 printResponse("SaveContext", cap, responseSize, responseCode, resp_buf); 2470 if (responseCode != TPM_RC_SUCCESS) 2471 return false; 2472 *size = responseSize - sizeof(TPM_RESPONSE); 2473 memcpy(saveArea, resp_buf + sizeof(TPM_RESPONSE), *size); 2474 return true; 2475 } 2476 2477 bool Tpm2_FlushContext(LocalTpm& tpm, TPM_HANDLE handle) { 2478 byte commandBuf[2*MAX_SIZE_PARAMS]; 2479 memset(commandBuf, 0, MAX_SIZE_PARAMS); 2480 2481 uint32_t big_endian_handle; 2482 int size_resp= MAX_SIZE_PARAMS; 2483 byte resp_buf[MAX_SIZE_PARAMS]; 2484 memset(resp_buf, 0, MAX_SIZE_PARAMS); 2485 2486 ChangeEndian32((uint32_t*)&handle, &big_endian_handle); 2487 int in_size = Tpm2_SetCommand(TPM_ST_NO_SESSIONS, TPM_CC_FlushContext, 2488 commandBuf, sizeof(TPM_HANDLE), 2489 (byte*)&big_endian_handle); 2490 printCommand("FlushContext", in_size, commandBuf); 2491 if (!tpm.SendCommand(in_size, commandBuf)) { 2492 printf("SendCommand failed\n"); 2493 return false; 2494 } 2495 if (!tpm.GetResponse(&size_resp, resp_buf)) { 2496 printf("GetResponse failed\n"); 2497 return false; 2498 } 2499 uint16_t cap = 0; 2500 uint32_t responseSize; 2501 uint32_t responseCode; 2502 Tpm2_InterpretResponse(size_resp, resp_buf, &cap, 2503 &responseSize, &responseCode); 2504 printResponse("FlushContext", cap, responseSize, responseCode, resp_buf); 2505 if (responseCode != TPM_RC_SUCCESS) 2506 return false; 2507 return true; 2508 } 2509 2510 TPM_HANDLE GetNvHandle(uint32_t slot) { 2511 return (TPM_HANDLE)((TPM_HT_NV_INDEX << HR_SHIFT) + slot); 2512 } 2513 2514 bool Tpm2_IncrementNv(LocalTpm& tpm, TPMI_RH_NV_INDEX index, string& authString) { 2515 byte commandBuf[2*MAX_SIZE_PARAMS]; 2516 int size_resp = MAX_SIZE_PARAMS; 2517 byte resp_buf[MAX_SIZE_PARAMS]; 2518 int size_params = 0; 2519 byte params_buf[MAX_SIZE_PARAMS]; 2520 int space_left = MAX_SIZE_PARAMS; 2521 byte* in = params_buf; 2522 int n; 2523 2524 memset(commandBuf, 0, MAX_SIZE_PARAMS); 2525 memset(resp_buf, 0, MAX_SIZE_PARAMS); 2526 2527 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint32_t)) 2528 ChangeEndian32((uint32_t*)&index, (uint32_t*)in); 2529 Update(sizeof(uint32_t), &in, &size_params, &space_left); 2530 2531 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint32_t)) 2532 ChangeEndian32((uint32_t*)&index, (uint32_t*)in); 2533 Update(sizeof(uint32_t), &in, &size_params, &space_left); 2534 2535 memset(in, 0, sizeof(uint16_t)); 2536 Update(sizeof(uint16_t), &in, &size_params, &space_left); 2537 2538 n = CreatePasswordAuthArea(authString, space_left, in); 2539 IF_NEG_RETURN_FALSE(n); 2540 Update(n, &in, &size_params, &space_left); 2541 2542 int in_size = Tpm2_SetCommand(TPM_ST_SESSIONS, TPM_CC_NV_Increment, 2543 commandBuf, size_params, params_buf); 2544 printCommand("IncrementNv", in_size, commandBuf); 2545 if (!tpm.SendCommand(in_size, commandBuf)) { 2546 printf("SendCommand failed\n"); 2547 return false; 2548 } 2549 if (!tpm.GetResponse(&size_resp, resp_buf)) { 2550 printf("GetResponse failed\n"); 2551 return false; 2552 } 2553 uint16_t cap = 0; 2554 uint32_t responseSize; 2555 uint32_t responseCode; 2556 Tpm2_InterpretResponse(size_resp, resp_buf, &cap, 2557 &responseSize, &responseCode); 2558 printResponse("IncrementNv", cap, responseSize, responseCode, resp_buf); 2559 if (responseCode != TPM_RC_SUCCESS) 2560 return false; 2561 2562 return true; 2563 } 2564 2565 bool Tpm2_ReadNv(LocalTpm& tpm, TPMI_RH_NV_INDEX index, 2566 string& authString, uint16_t* size, byte* data) { 2567 byte commandBuf[2*MAX_SIZE_PARAMS]; 2568 int size_resp = MAX_SIZE_PARAMS; 2569 byte resp_buf[MAX_SIZE_PARAMS]; 2570 memset(resp_buf, 0, MAX_SIZE_PARAMS); 2571 int size_params = 0; 2572 byte params_buf[MAX_SIZE_PARAMS]; 2573 int space_left = MAX_SIZE_PARAMS; 2574 byte* in = params_buf; 2575 int n; 2576 2577 memset(commandBuf, 0, MAX_SIZE_PARAMS); 2578 memset(params_buf, 0, MAX_SIZE_PARAMS); 2579 2580 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint32_t)) 2581 ChangeEndian32((uint32_t*)&index, (uint32_t*)in); 2582 Update(sizeof(uint32_t), &in, &size_params, &space_left); 2583 2584 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint32_t)) 2585 ChangeEndian32((uint32_t*)&index, (uint32_t*)in); 2586 Update(sizeof(uint32_t), &in, &size_params, &space_left); 2587 2588 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)) 2589 memset(in, 0, sizeof(uint16_t)); 2590 Update(sizeof(uint16_t), &in, &size_params, &space_left); 2591 2592 n = CreatePasswordAuthArea(authString, space_left, in); 2593 IF_NEG_RETURN_FALSE(n); 2594 Update(n, &in, &size_params, &space_left); 2595 memset(in, 0, sizeof(uint16_t)); 2596 2597 uint16_t offset = 0; 2598 ChangeEndian16((uint16_t*)size, (uint16_t*)in); 2599 Update(sizeof(uint16_t), &in, &size_params, &space_left); 2600 IF_NEG_RETURN_FALSE(n); 2601 ChangeEndian16((uint16_t*)&offset, (uint16_t*)in); 2602 Update(sizeof(uint16_t), &in, &size_params, &space_left); 2603 2604 int in_size = Tpm2_SetCommand(TPM_ST_SESSIONS, TPM_CC_NV_Read, 2605 commandBuf, size_params, params_buf); 2606 printCommand("ReadNv", in_size, commandBuf); 2607 if (!tpm.SendCommand(in_size, commandBuf)) { 2608 printf("SendCommand failed\n"); 2609 return false; 2610 } 2611 if (!tpm.GetResponse(&size_resp, resp_buf)) { 2612 printf("GetResponse failed\n"); 2613 return false; 2614 } 2615 uint16_t cap = 0; 2616 uint32_t responseSize; 2617 uint32_t responseCode; 2618 Tpm2_InterpretResponse(size_resp, resp_buf, &cap, 2619 &responseSize, &responseCode); 2620 printResponse("ReadNv", cap, responseSize, responseCode, resp_buf); 2621 if (responseCode != TPM_RC_SUCCESS) 2622 return false; 2623 byte* out = resp_buf + sizeof(TPM_RESPONSE) + sizeof(uint32_t); 2624 ChangeEndian16((uint16_t*)out, (uint16_t*)size); 2625 out += sizeof(uint16_t); 2626 memcpy(data, out, *size); 2627 return true; 2628 } 2629 2630 bool Tpm2_WriteNv(LocalTpm& tpm, TPMI_RH_NV_INDEX index, 2631 string& authString, uint16_t size, byte* data) { 2632 byte commandBuf[2*MAX_SIZE_PARAMS]; 2633 int size_resp = MAX_SIZE_PARAMS; 2634 byte resp_buf[MAX_SIZE_PARAMS]; 2635 int size_params = 0; 2636 byte params_buf[MAX_SIZE_PARAMS]; 2637 int space_left = MAX_SIZE_PARAMS; 2638 byte* in = params_buf; 2639 int n; 2640 2641 memset(commandBuf, 0, MAX_SIZE_PARAMS); 2642 memset(resp_buf, 0, MAX_SIZE_PARAMS); 2643 2644 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint32_t)) 2645 ChangeEndian32((uint32_t*)&index, (uint32_t*)in); 2646 Update(sizeof(uint32_t), &in, &size_params, &space_left); 2647 2648 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint32_t)) 2649 ChangeEndian32((uint32_t*)&index, (uint32_t*)in); 2650 Update(sizeof(uint32_t), &in, &size_params, &space_left); 2651 2652 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)) 2653 memset(in, 0, sizeof(uint16_t)); 2654 Update(sizeof(uint16_t), &in, &size_params, &space_left); 2655 2656 n = CreatePasswordAuthArea(authString, space_left, in); 2657 IF_NEG_RETURN_FALSE(n); 2658 Update(n, &in, &size_params, &space_left); 2659 2660 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)) 2661 ChangeEndian16((uint16_t*)&size, (uint16_t*)in); 2662 Update(sizeof(uint16_t), &in, &size_params, &space_left); 2663 2664 IF_LESS_THAN_RETURN_FALSE(space_left, size) 2665 memcpy(in, data, size); 2666 Update(size, &in, &size_params, &space_left); 2667 2668 uint16_t offset = 0; 2669 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)) 2670 ChangeEndian16((uint16_t*)&offset, (uint16_t*)in); 2671 Update(sizeof(uint16_t), &in, &size_params, &space_left); 2672 2673 int in_size = Tpm2_SetCommand(TPM_ST_SESSIONS, TPM_CC_NV_Write, 2674 commandBuf, size_params, params_buf); 2675 printCommand("WriteNv", in_size, commandBuf); 2676 if (!tpm.SendCommand(in_size, commandBuf)) { 2677 printf("SendCommand failed\n"); 2678 return false; 2679 } 2680 if (!tpm.GetResponse(&size_resp, resp_buf)) { 2681 printf("GetResponse failed\n"); 2682 return false; 2683 } 2684 uint16_t cap = 0; 2685 uint32_t responseSize; 2686 uint32_t responseCode; 2687 Tpm2_InterpretResponse(size_resp, resp_buf, &cap, 2688 &responseSize, &responseCode); 2689 printResponse("WriteNv", cap, responseSize, responseCode, resp_buf); 2690 if (responseCode != TPM_RC_SUCCESS) 2691 return false; 2692 return true; 2693 } 2694 2695 bool Tpm2_DefineSpace(LocalTpm& tpm, TPM_HANDLE owner, TPMI_RH_NV_INDEX index, 2696 string& authString, uint16_t authPolicySize, byte* authPolicy, 2697 uint32_t attributes, uint16_t size_data) { 2698 byte commandBuf[2*MAX_SIZE_PARAMS]; 2699 int size_resp = MAX_SIZE_PARAMS; 2700 byte resp_buf[MAX_SIZE_PARAMS]; 2701 int size_params = 0; 2702 byte params_buf[MAX_SIZE_PARAMS]; 2703 int space_left = MAX_SIZE_PARAMS; 2704 byte* in = params_buf; 2705 2706 memset(commandBuf, 0, MAX_SIZE_PARAMS); 2707 memset(resp_buf, 0, MAX_SIZE_PARAMS); 2708 2709 int n = SetOwnerHandle(owner, space_left, in); 2710 IF_NEG_RETURN_FALSE(n); 2711 Update(n, &in, &size_params, &space_left);; 2712 2713 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)) 2714 memset(in, 0, sizeof(uint16_t)); 2715 Update(sizeof(uint16_t), &in, &size_params, &space_left); 2716 2717 string emptyAuth; 2718 n = CreatePasswordAuthArea(emptyAuth, space_left, in); 2719 2720 IF_NEG_RETURN_FALSE(n); 2721 Update(n, &in, &size_params, &space_left); 2722 2723 n = SetPasswordData(authString, space_left, in); 2724 IF_NEG_RETURN_FALSE(n); 2725 Update(n, &in, &size_params, &space_left); 2726 2727 // TPM2B_NV_PUBLIC 2728 uint16_t size_nv_area = sizeof(uint32_t) + sizeof(TPMI_RH_NV_INDEX) + 2729 sizeof(TPMI_ALG_HASH) + 2*sizeof(uint16_t) + 2730 authPolicySize; 2731 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)) 2732 ChangeEndian16((uint16_t*)&size_nv_area, (uint16_t*)in); 2733 Update(sizeof(uint16_t), &in, &size_params, &space_left); 2734 2735 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint32_t)) 2736 2737 // nvIndex; 2738 ChangeEndian32((uint32_t*)&index, (uint32_t*)in); 2739 Update(sizeof(uint32_t), &in, &size_params, &space_left); 2740 2741 // TPMI_ALG_HASH alg = TPM_ALG_SHA256; 2742 TPMI_ALG_HASH alg = TPM_ALG_SHA1; 2743 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)) 2744 ChangeEndian16((uint16_t*)&alg, (uint16_t*)in); 2745 Update(sizeof(uint16_t), &in, &size_params, &space_left); 2746 2747 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint32_t)) 2748 ChangeEndian32((uint32_t*)&attributes, (uint32_t*)in); 2749 Update(sizeof(uint32_t), &in, &size_params, &space_left); 2750 2751 // authPolicy size 2752 ChangeEndian16((uint16_t*)&authPolicySize, (uint16_t*)in); 2753 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)) 2754 Update(sizeof(uint16_t), &in, &size_params, &space_left); 2755 if (authPolicySize > 0) { 2756 IF_LESS_THAN_RETURN_FALSE(space_left, authPolicySize) 2757 memcpy(in, authPolicy, authPolicySize); 2758 Update(authPolicySize, &in, &size_params, &space_left); 2759 } 2760 2761 // dataSize 2762 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)) 2763 ChangeEndian16((uint16_t*)&size_data, (uint16_t*)in); 2764 Update(sizeof(uint16_t), &in, &size_params, &space_left); 2765 2766 int in_size = Tpm2_SetCommand(TPM_ST_SESSIONS, TPM_CC_NV_DefineSpace, 2767 commandBuf, size_params, params_buf); 2768 printCommand("DefineSpace", in_size, commandBuf); 2769 if (!tpm.SendCommand(in_size, commandBuf)) { 2770 printf("SendCommand failed\n"); 2771 return false; 2772 } 2773 if (!tpm.GetResponse(&size_resp, resp_buf)) { 2774 printf("GetResponse failed\n"); 2775 return false; 2776 } 2777 uint16_t cap = 0; 2778 uint32_t responseSize; 2779 uint32_t responseCode; 2780 Tpm2_InterpretResponse(size_resp, resp_buf, &cap, 2781 &responseSize, &responseCode); 2782 printResponse("Definespace", cap, responseSize, responseCode, resp_buf); 2783 if (responseCode != TPM_RC_SUCCESS) 2784 return false; 2785 return true; 2786 } 2787 2788 bool Tpm2_UndefineSpace(LocalTpm& tpm, TPM_HANDLE owner, TPMI_RH_NV_INDEX index) { 2789 byte commandBuf[2*MAX_SIZE_PARAMS]; 2790 int size_resp = MAX_SIZE_PARAMS; 2791 byte resp_buf[MAX_SIZE_PARAMS]; 2792 int size_params = 0; 2793 byte params_buf[MAX_SIZE_PARAMS]; 2794 int space_left = MAX_SIZE_PARAMS; 2795 byte* in = params_buf; 2796 int n; 2797 2798 memset(commandBuf, 0, MAX_SIZE_PARAMS); 2799 memset(resp_buf, 0, MAX_SIZE_PARAMS); 2800 2801 n = SetOwnerHandle(owner, space_left, params_buf); 2802 IF_NEG_RETURN_FALSE(n); 2803 Update(n, &in, &size_params, &space_left); 2804 2805 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint32_t)) 2806 ChangeEndian32((uint32_t*)&index, (uint32_t*)in); 2807 Update(sizeof(uint32_t), &in, &size_params, &space_left); 2808 2809 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)) 2810 memset(in, 0, sizeof(uint16_t)); 2811 Update(sizeof(uint16_t), &in, &size_params, &space_left); 2812 2813 string emptyAuth; 2814 n = CreatePasswordAuthArea(emptyAuth, space_left, in); 2815 IF_NEG_RETURN_FALSE(n); 2816 Update(n, &in, &size_params, &space_left); 2817 2818 int in_size = Tpm2_SetCommand(TPM_ST_SESSIONS, TPM_CC_NV_UndefineSpace, 2819 commandBuf, size_params, params_buf); 2820 printCommand("UndefineSpace", in_size, commandBuf); 2821 if (!tpm.SendCommand(in_size, commandBuf)) { 2822 printf("SendCommand failed\n"); 2823 return false; 2824 } 2825 if (!tpm.GetResponse(&size_resp, resp_buf)) { 2826 printf("GetResponse failed\n"); 2827 return false; 2828 } 2829 uint16_t cap = 0; 2830 uint32_t responseSize; 2831 uint32_t responseCode; 2832 Tpm2_InterpretResponse(size_resp, resp_buf, &cap, 2833 &responseSize, &responseCode); 2834 printResponse("UndefineSpace", cap, responseSize, responseCode, resp_buf); 2835 if (responseCode != TPM_RC_SUCCESS) 2836 return false; 2837 return true; 2838 } 2839 2840 bool Tpm2_DictionaryAttackLockReset(LocalTpm& tpm) { 2841 byte commandBuf[2*MAX_SIZE_PARAMS]; 2842 memset(commandBuf, 0, 2*MAX_SIZE_PARAMS); 2843 2844 int size_resp = MAX_SIZE_PARAMS; 2845 byte resp_buf[MAX_SIZE_PARAMS]; 2846 memset(resp_buf, 0, MAX_SIZE_PARAMS); 2847 int size_params = 0; 2848 byte params_buf[MAX_SIZE_PARAMS]; 2849 memset(params_buf, 0, MAX_SIZE_PARAMS); 2850 byte* current_out = params_buf; 2851 TPM_HANDLE handle = TPM_RH_LOCKOUT; 2852 2853 ChangeEndian32((uint32_t*)&handle, (uint32_t*)current_out); 2854 size_params += sizeof(uint32_t); 2855 current_out += sizeof(uint32_t); 2856 2857 int in_size = Tpm2_SetCommand(TPM_ST_NO_SESSIONS, 2858 TPM_CC_DictionaryAttackLockReset, 2859 commandBuf, size_params, params_buf); 2860 printCommand("DictionaryAttackLockReset", in_size, commandBuf); 2861 if (!tpm.SendCommand(in_size, commandBuf)) { 2862 printf("SendCommand failed\n"); 2863 return false; 2864 } 2865 if (!tpm.GetResponse(&size_resp, resp_buf)) { 2866 printf("GetResponse failed\n"); 2867 return false; 2868 } 2869 uint16_t cap = 0; 2870 uint32_t responseSize; 2871 uint32_t responseCode; 2872 Tpm2_InterpretResponse(size_resp, resp_buf, &cap, 2873 &responseSize, &responseCode); 2874 printResponse("DictionaryAttackLockReset", cap, responseSize, 2875 responseCode, resp_buf); 2876 if (responseCode != TPM_RC_SUCCESS) 2877 return false; 2878 return true; 2879 } 2880 2881 bool Tpm2_Flushall(LocalTpm& tpm, uint32_t start) { 2882 int size = MAX_SIZE_PARAMS; 2883 byte buf[MAX_SIZE_PARAMS]; 2884 2885 if (!Tpm2_GetCapability(tpm, TPM_CAP_HANDLES, start, &size, buf)) { 2886 printf("Flushall can't get capabilities\n"); 2887 return false; 2888 } 2889 uint32_t cap; 2890 uint32_t count; 2891 uint32_t handle; 2892 byte* current_in = buf; 2893 2894 current_in += 1; 2895 ChangeEndian32((uint32_t*)current_in, &cap); 2896 current_in += sizeof(uint32_t); 2897 if (cap != TPM_CAP_HANDLES) { 2898 printf("Flushall: didn't get handles\n"); 2899 return false; 2900 } 2901 while (current_in < (size+buf)) { 2902 uint32_t i; 2903 ChangeEndian32((uint32_t*)current_in, &count); 2904 current_in += sizeof(uint32_t); 2905 for (i = 0; i < count; i++) { 2906 ChangeEndian32((uint32_t*)current_in, &handle); 2907 current_in += sizeof(uint32_t); 2908 printf("deleting handle: %08x\n", handle); 2909 Tpm2_FlushContext(tpm, handle); 2910 } 2911 } 2912 return true; 2913 } 2914 2915 bool Tpm2_Rsa_Encrypt(LocalTpm& tpm, TPM_HANDLE handle, string& authString, 2916 TPM2B_PUBLIC_KEY_RSA& inData, TPMT_RSA_DECRYPT& scheme, 2917 TPM2B_DATA& label, TPM2B_PUBLIC_KEY_RSA* outData) { 2918 byte commandBuf[2*MAX_SIZE_PARAMS]; 2919 int size_resp = MAX_SIZE_PARAMS; 2920 byte resp_buf[MAX_SIZE_PARAMS]; 2921 int size_params = 0; 2922 byte params_buf[MAX_SIZE_PARAMS]; 2923 int space_left = MAX_SIZE_PARAMS; 2924 byte* in = params_buf; 2925 int n; 2926 2927 memset(commandBuf, 0, MAX_SIZE_PARAMS); 2928 memset(resp_buf, 0, MAX_SIZE_PARAMS); 2929 2930 n = SetPasswordData(authString, space_left, in); 2931 IF_NEG_RETURN_FALSE(n); 2932 Update(n, &in, &size_params, &space_left); 2933 2934 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint32_t)) 2935 ChangeEndian32((uint32_t*)&handle, (uint32_t*)in); 2936 Update(sizeof(uint32_t), &in, &size_params, &space_left); 2937 2938 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)) 2939 ChangeEndian16((uint16_t*)&inData.size, (uint16_t*)in); 2940 Update(sizeof(uint16_t), &in, &size_params, &space_left); 2941 IF_LESS_THAN_RETURN_FALSE(space_left, inData.size) 2942 memcpy(in, inData.buffer, inData.size); 2943 Update(inData.size, &in, &size_params, &space_left); 2944 2945 scheme.scheme = TPM_ALG_NULL; 2946 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)) 2947 ChangeEndian16((uint16_t*)&scheme.scheme, (uint16_t*)in); 2948 Update(sizeof(uint16_t), &in, &size_params, &space_left); 2949 2950 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)) 2951 ChangeEndian16((uint16_t*)&label.size, (uint16_t*)in); 2952 Update(sizeof(uint16_t), &in, &size_params, &space_left); 2953 2954 IF_LESS_THAN_RETURN_FALSE(space_left, label.size) 2955 memcpy(in, label.buffer, label.size); 2956 Update(label.size, &in, &size_params, &space_left); 2957 2958 int in_size = Tpm2_SetCommand(TPM_ST_SESSIONS, TPM_CC_RSA_Encrypt, 2959 commandBuf, size_params, params_buf); 2960 printCommand("TPM_CC_RSA_Encrypt", in_size, commandBuf); 2961 if (!tpm.SendCommand(in_size, commandBuf)) { 2962 printf("SendCommand failed\n"); 2963 return false; 2964 } 2965 if (!tpm.GetResponse(&size_resp, resp_buf)) { 2966 printf("GetResponse failed\n"); 2967 return false; 2968 } 2969 uint16_t cap = 0; 2970 uint32_t responseSize; 2971 uint32_t responseCode; 2972 Tpm2_InterpretResponse(size_resp, resp_buf, &cap, 2973 &responseSize, &responseCode); 2974 printResponse("TPM_RSA_Encrypt", cap, responseSize, responseCode, resp_buf); 2975 if (responseCode != TPM_RC_SUCCESS) 2976 return false; 2977 byte* out = resp_buf + sizeof(TPM_RESPONSE); 2978 ChangeEndian16((uint16_t*)out, &outData->size); 2979 out += sizeof(uint16_t); 2980 memcpy(outData->buffer, out, outData->size); 2981 out += outData->size; 2982 return true; 2983 } 2984 2985 bool Tpm2_EvictControl(LocalTpm& tpm, TPMI_RH_PROVISION owner, 2986 TPM_HANDLE handle, string& authString, 2987 TPMI_DH_PERSISTENT persistantHandle) { 2988 byte commandBuf[2*MAX_SIZE_PARAMS]; 2989 int size_resp = MAX_SIZE_PARAMS; 2990 byte resp_buf[MAX_SIZE_PARAMS]; 2991 int size_params = 0; 2992 byte params_buf[MAX_SIZE_PARAMS]; 2993 int space_left = MAX_SIZE_PARAMS; 2994 byte* in = params_buf; 2995 int n; 2996 2997 memset(commandBuf, 0, MAX_SIZE_PARAMS); 2998 memset(resp_buf, 0, MAX_SIZE_PARAMS); 2999 3000 n = SetOwnerHandle(owner, space_left, in); 3001 IF_NEG_RETURN_FALSE(n); 3002 Update(n, &in, &size_params, &space_left); 3003 3004 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint32_t)) 3005 ChangeEndian32((uint32_t*)&handle, (uint32_t*)in); 3006 Update(sizeof(uint32_t), &in, &size_params, &space_left); 3007 3008 uint16_t hack = 0; 3009 ChangeEndian16((uint16_t*)&hack, (uint16_t*)in); 3010 Update(sizeof(uint16_t), &in, &size_params, &space_left); 3011 3012 string emptyAuth; 3013 n = CreatePasswordAuthArea(emptyAuth, space_left, in); 3014 IF_NEG_RETURN_FALSE(n); 3015 Update(n, &in, &size_params, &space_left); 3016 3017 #if 0 3018 n = SetPasswordData(authString, space_left, in); 3019 IF_NEG_RETURN_FALSE(n); 3020 Update(n, &in, &size_params, &space_left); 3021 #endif 3022 3023 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint32_t)) 3024 ChangeEndian32((uint32_t*)&persistantHandle, (uint32_t*)in); 3025 Update(sizeof(uint32_t), &in, &size_params, &space_left); 3026 3027 int in_size = Tpm2_SetCommand(TPM_ST_SESSIONS, TPM_CC_EvictControl, 3028 commandBuf, size_params, params_buf); 3029 printCommand("EvictControl", in_size, commandBuf); 3030 if (!tpm.SendCommand(in_size, commandBuf)) { 3031 printf("SendCommand failed\n"); 3032 return false; 3033 } 3034 if (!tpm.GetResponse(&size_resp, resp_buf)) { 3035 printf("GetResponse failed\n"); 3036 return false; 3037 } 3038 uint16_t cap = 0; 3039 uint32_t responseSize; 3040 uint32_t responseCode; 3041 Tpm2_InterpretResponse(size_resp, resp_buf, &cap, 3042 &responseSize, &responseCode); 3043 printResponse("EvictControl", cap, responseSize, responseCode, resp_buf); 3044 if (responseCode != TPM_RC_SUCCESS) 3045 return false; 3046 #if 0 3047 byte* out = resp_buf + sizeof(TPM_RESPONSE); 3048 ChangeEndian32((uint32_t*)out, &persistantHandle); 3049 out += sizeof(uint32_t); 3050 #endif 3051 return true; 3052 } 3053 3054 #define DEBUG 3055 3056 // 1. Generate Seed 3057 // 2. encrypted_secret= E(protector_key, seed || "IDENTITY") 3058 // 3. symKey ≔ KDFa (ekNameAlg, seed, “STORAGE”, name, NULL , bits) 3059 // 4. encIdentity ≔ AesCFB(symKey, 0, credential) 3060 // 5. HMACkey ≔ KDFa (ekNameAlg, seed, “INTEGRITY”, NULL, NULL, bits) 3061 // 6. outerHMAC ≔ HMAC(HMACkey, encIdentity || Name) 3062 bool MakeCredential(int size_endorsement_blob, byte* endorsement_blob, 3063 TPM_ALG_ID hash_alg_id, 3064 TPM2B_DIGEST& unmarshaled_credential, 3065 TPM2B_DIGEST& marshaled_credential, 3066 TPM2B_NAME& unmarshaled_name, 3067 TPM2B_NAME& marshaled_name, 3068 int* size_encIdentity, byte* encIdentity, 3069 TPM2B_ENCRYPTED_SECRET* unmarshaled_encrypted_secret, 3070 TPM2B_ENCRYPTED_SECRET* marshaled_encrypted_secret, 3071 TPM2B_DIGEST* unmarshaled_integrityHmac, 3072 TPM2B_DIGEST* marshaled_integrityHmac) { 3073 X509* endorsement_cert = nullptr; 3074 int size_seed = 16; 3075 byte seed[32]; 3076 int size_secret = 256; 3077 byte secret_buf[256]; 3078 byte zero_iv[32]; 3079 byte symKey[MAX_SIZE_PARAMS]; 3080 string label; 3081 string key; 3082 string contextU; 3083 string contextV; 3084 string name; 3085 3086 memset(zero_iv, 0, 32); 3087 #ifdef DEBUG 3088 printf("MakeCredential\n"); 3089 #endif 3090 3091 // 1. Generate seed 3092 RAND_bytes(seed, size_seed); 3093 3094 // Get endorsement public key, which is protector key 3095 byte* p = endorsement_blob; 3096 endorsement_cert = d2i_X509(nullptr, (const byte**)&p, size_endorsement_blob); 3097 EVP_PKEY* protector_evp_key = X509_get_pubkey(endorsement_cert); 3098 RSA* protector_key = EVP_PKEY_get1_RSA(protector_evp_key); 3099 RSA_up_ref(protector_key); 3100 3101 // 2. Secret= E(protector_key, seed || "IDENTITY") 3102 // args: to, from, label, len 3103 size_secret= 256; 3104 RSA_padding_add_PKCS1_OAEP(secret_buf, 256, seed, size_seed, 3105 (byte*)"IDENTITY", strlen("IDENTITY")+1); 3106 #ifdef DEBUG 3107 int k = 0; 3108 byte check[512]; 3109 memset(check, 0, 512); 3110 while(k < 256 && secret_buf[k] == 0) k++; 3111 int check_len = RSA_padding_check_PKCS1_OAEP(check, 256, &secret_buf[k], 256-k, 3112 256, (byte*)"IDENTITY", strlen("IDENTITY")+1); 3113 printf("Seed : ");PrintBytes(size_seed, seed);printf("\n"); 3114 printf("Funny padding: ");PrintBytes(256, secret_buf);printf("\n"); 3115 printf("check %03d : ", check_len);PrintBytes(check_len, check);printf("\n"); 3116 #endif 3117 int n = RSA_public_encrypt(size_secret, secret_buf, 3118 unmarshaled_encrypted_secret->secret, 3119 protector_key, RSA_NO_PADDING); 3120 if (n <=0) 3121 return false; 3122 unmarshaled_encrypted_secret->size = n; 3123 ChangeEndian16((uint16_t*)&unmarshaled_encrypted_secret->size, 3124 &marshaled_encrypted_secret->size); 3125 memcpy(marshaled_encrypted_secret->secret, unmarshaled_encrypted_secret->secret, 3126 unmarshaled_encrypted_secret->size); 3127 3128 // 3. Calculate symKey 3129 label = "STORAGE"; 3130 key.assign((const char*)seed, size_seed); 3131 contextV.clear(); 3132 name.assign((const char*)unmarshaled_name.name, unmarshaled_name.size); 3133 if (!KDFa(hash_alg_id, key, label, name, contextV, 128, 32, symKey)) { 3134 printf("Can't KDFa symKey\n"); 3135 return false; 3136 } 3137 3138 // 4. encIdentity 3139 if (!AesCFBEncrypt(symKey, unmarshaled_credential.size + sizeof(uint16_t), 3140 (byte*)&marshaled_credential, 16, zero_iv, 3141 size_encIdentity, encIdentity)) { 3142 printf("Can't AesCFBEncrypt\n"); 3143 return false; 3144 } 3145 3146 int size_hmacKey = SizeHash(hash_alg_id); 3147 byte hmacKey[128]; 3148 3149 // 5. HMACkey ≔ KDFa (ekNameAlg, seed, “INTEGRITY”, NULL, NULL, bits) 3150 label = "INTEGRITY"; 3151 if (!KDFa(hash_alg_id, key, label, contextV, contextV, 3152 8 * SizeHash(hash_alg_id), 32, hmacKey)) { 3153 printf("Can't KDFa hmacKey\n"); 3154 return false; 3155 } 3156 3157 // 6. Calculate outerMac = HMAC(hmacKey, encIdentity || name); 3158 HMAC_CTX hctx; 3159 HMAC_CTX_init(&hctx); 3160 if (hash_alg_id == TPM_ALG_SHA1) { 3161 HMAC_Init_ex(&hctx, hmacKey, size_hmacKey, EVP_sha1(), nullptr); 3162 } else { 3163 HMAC_Init_ex(&hctx, hmacKey, size_hmacKey, EVP_sha256(), nullptr); 3164 } 3165 HMAC_Update(&hctx, (const byte*)encIdentity, (size_t)*size_encIdentity); 3166 HMAC_Update(&hctx, (const byte*)name.data(), name.size()); 3167 // HMAC_Update(&hctx, (const byte*)&marshaled_name.name, name.size()); 3168 unmarshaled_integrityHmac->size = size_hmacKey; 3169 HMAC_Final(&hctx, unmarshaled_integrityHmac->buffer, (uint32_t*)&size_hmacKey); 3170 HMAC_CTX_cleanup(&hctx); 3171 3172 // integrityHMAC 3173 ChangeEndian16((uint16_t*)&size_hmacKey, &marshaled_integrityHmac->size); 3174 memcpy(marshaled_integrityHmac->buffer, unmarshaled_integrityHmac->buffer, 3175 size_hmacKey); 3176 #ifdef DEBUG 3177 printf("encIdentity: "); PrintBytes(*size_encIdentity, (byte*)encIdentity); printf("\n"); 3178 printf("name : "); PrintBytes(name.size(), (byte*)name.data()); printf("\n"); 3179 printf("hmac : "); PrintBytes(size_hmacKey, (byte*)unmarshaled_integrityHmac->buffer); printf("\n"); 3180 printf("marsh-hmac : "); PrintBytes(size_hmacKey + 2, (byte*)&marshaled_integrityHmac); printf("\n"); 3181 #endif 3182 return true; 3183 } 3184 3185 // encrypted_data_hmac is an input argument for decrypt and 3186 // an output argument for encrypt. 3187 bool EncryptDataWithCredential(bool encrypt_flag, TPM_ALG_ID hash_alg_id, 3188 TPM2B_DIGEST unmarshaled_credential, 3189 TPM2B_DIGEST marshaled_credential, 3190 int size_input_data, byte* input_data, 3191 int* size_hmac, byte* encrypted_data_hmac, 3192 int* size_output_data, byte* output_data) { 3193 int size_derived_keys = 128; 3194 byte derived_keys[128]; 3195 byte decrypt_mac[128]; 3196 string data_encryption_key_seed; 3197 string label; 3198 string contextV; 3199 byte* encrypted_data = output_data; 3200 3201 *size_hmac = SizeHash(hash_alg_id); 3202 data_encryption_key_seed.assign((const char*)unmarshaled_credential.buffer, 3203 unmarshaled_credential.size); 3204 label = "PROTECT"; 3205 if (!KDFa(hash_alg_id, data_encryption_key_seed, label, contextV, contextV, 256, 3206 size_derived_keys, derived_keys)) { 3207 printf("Can't derive protection keys\n"); 3208 return false; 3209 } 3210 3211 memset(output_data, 0, *size_output_data); 3212 if (!AesCtrCrypt(128, derived_keys, size_input_data, input_data, output_data)) { 3213 printf("Can't encrypt input\n"); 3214 return false; 3215 } 3216 *size_output_data = size_input_data; 3217 if (!encrypt_flag) 3218 encrypted_data = input_data; 3219 else 3220 encrypted_data = output_data; 3221 HMAC_CTX hctx; 3222 HMAC_CTX_init(&hctx); 3223 if (hash_alg_id == TPM_ALG_SHA1) { 3224 HMAC_Init_ex(&hctx, &derived_keys[16], 16, EVP_sha1(), nullptr); 3225 *size_hmac = 20; 3226 } else { 3227 HMAC_Init_ex(&hctx, &derived_keys[16], 16, EVP_sha256(), nullptr); 3228 *size_hmac = 32; 3229 } 3230 HMAC_Update(&hctx, encrypted_data, size_input_data); 3231 if (encrypt_flag) { 3232 HMAC_Final(&hctx, encrypted_data_hmac, (uint32_t*)size_hmac); 3233 HMAC_CTX_cleanup(&hctx); 3234 } else { 3235 HMAC_Final(&hctx, decrypt_mac, (uint32_t*)size_hmac); 3236 HMAC_CTX_cleanup(&hctx); 3237 if (memcmp(decrypt_mac, encrypted_data_hmac, *size_hmac) != 0) 3238 return false; 3239 } 3240 3241 return true; 3242 } 3243 3244 /* 3245 * The following code is for an encrypted session. Later we should fix the 3246 * original functions so they allow bound sessions initiated with encrypted salts. 3247 * 3248 * This code works for HMAC sessions only with password authorization. 3249 */ 3250 3251 // Name = nameAlg || Hash(nvPublicArea) 3252 // nvPublicArea 3253 // TPMI_RH_NV_INDEX nvIndex; 3254 // TPMI_ALG_HASH nameAlg; 3255 // TPMA_NV attributes; 3256 // TPM2B_DIGEST authPolicy; 3257 // uint16_t dataSize; 3258 bool CalculateNvName(ProtectedSessionAuthInfo& in, TPM_HANDLE nv_handle, 3259 uint16_t nv_hash_alg, uint32_t nv_attributes, 3260 uint16_t data_size, bool wasWritten, byte* out) { 3261 SHA_CTX sha1; 3262 SHA256_CTX sha256; 3263 byte toHash[256]; 3264 uint16_t zero = 0; 3265 3266 if (in.hash_alg_!= TPM_ALG_SHA1 && in.hash_alg_ != TPM_ALG_SHA256) { 3267 printf("CalculateNvName: unsupported hash algorithm\n"); 3268 return false; 3269 } 3270 3271 ChangeEndian16(&nv_hash_alg, (uint16_t*)out); 3272 3273 int current_out_size = 0; 3274 int room_left = 256; 3275 byte* current = toHash; 3276 3277 uint32_t new_attributes = nv_attributes; 3278 if (wasWritten) 3279 new_attributes |= NV_WRITTEN; 3280 3281 ChangeEndian32((uint32_t*)&nv_handle, (uint32_t*)current); 3282 Update(sizeof(uint32_t), ¤t, ¤t_out_size, &room_left); 3283 ChangeEndian16(&nv_hash_alg, (uint16_t*)current); 3284 Update(sizeof(uint16_t), ¤t, ¤t_out_size, &room_left); 3285 ChangeEndian32(&new_attributes, (uint32_t*)current); 3286 Update(sizeof(uint32_t), ¤t, ¤t_out_size, &room_left); 3287 ChangeEndian16(&zero, (uint16_t*)current); 3288 Update(sizeof(uint16_t), ¤t, ¤t_out_size, &room_left); 3289 ChangeEndian16(&data_size, (uint16_t*)current); 3290 Update(sizeof(uint16_t), ¤t, ¤t_out_size, &room_left); 3291 3292 printf("\nCalculateNvName hash buf: "); 3293 PrintBytes(current_out_size, toHash); printf("\n"); 3294 3295 int size_out = 0; 3296 if (in.hash_alg_ == TPM_ALG_SHA1) { 3297 3298 SHA1_Init(&sha1); 3299 SHA1_Update(&sha1, toHash, current_out_size); 3300 SHA1_Final(out + 2, &sha1); 3301 size_out = 22; 3302 } else { 3303 SHA256_Init(&sha256); 3304 SHA256_Update(&sha256, toHash, current_out_size); 3305 SHA256_Final(out + 2, &sha256); 3306 size_out = 34; 3307 } 3308 3309 printf("CalculateNvName name: "); 3310 PrintBytes(size_out, out); printf("\n"); 3311 return true; 3312 } 3313 3314 bool CalculateBindName(LocalTpm& tpm, TPM_HANDLE bind_obj, 3315 ProtectedSessionAuthInfo& authInfo) { 3316 uint16_t pub_blob_size = 4096; 3317 byte pub_blob[4096]; 3318 TPM2B_PUBLIC outPublic; 3319 TPM2B_NAME pub_name; 3320 TPM2B_NAME qualified_pub_name; 3321 3322 if (Tpm2_ReadPublic(tpm, bind_obj, &pub_blob_size, pub_blob, &outPublic, &pub_name, 3323 &qualified_pub_name)) { 3324 printf("ReadPublic succeeded\n"); 3325 } else { 3326 printf("ReadPublic failed\n"); 3327 return false; 3328 } 3329 printf("Public blob: "); 3330 PrintBytes(pub_blob_size, pub_blob); 3331 printf("\n"); 3332 printf("Name: "); 3333 PrintBytes(pub_name.size, pub_name.name); 3334 printf("\n"); 3335 printf("Qualified name: "); 3336 PrintBytes(qualified_pub_name.size, qualified_pub_name.name); 3337 printf("\n"); 3338 authInfo.nameProtected_.size = pub_name.size; 3339 memcpy(authInfo.nameProtected_.name, pub_name.name, pub_name.size); 3340 return true; 3341 } 3342 3343 3344 // HMac(sessionkey||auth, cpHash, nonceNewer, nonceOlder, sessionAttrs) 3345 // cpHash ≔ Hash(commandCode {|| Name1 {|| Name2 {|| Name3 }}} {|| parameters }) 3346 bool CalculateSessionHmac(ProtectedSessionAuthInfo& in, bool dir, uint32_t cmd, 3347 int numNames, TPM2B_NAME* names, 3348 int size_parms, byte* parms, int* size_hmac, byte* hmac) { 3349 SHA_CTX sha1; 3350 SHA256_CTX sha256; 3351 byte toHash[256]; 3352 byte cpHash[32]; 3353 3354 #if 1 3355 printf("\nCalculateSessionHmac\n"); 3356 #endif 3357 3358 if (in.hash_alg_!= TPM_ALG_SHA1 && in.hash_alg_ != TPM_ALG_SHA256) { 3359 printf("CalculateSessionHmac: unsupported hash algorithm\n"); 3360 return false; 3361 } 3362 3363 // Need to include auth too? 3364 byte hmac_key[256]; 3365 int sizeHmacKey = 0; 3366 3367 memcpy(hmac_key, in.sessionKey_, in.sessionKeySize_); 3368 sizeHmacKey += in.sessionKeySize_; 3369 3370 memcpy(&hmac_key[in.sessionKeySize_], in.targetAuthValue_.buffer, 3371 in.targetAuthValue_.size); 3372 sizeHmacKey += in.targetAuthValue_.size; 3373 3374 #if 1 3375 printf("hmac_key: "); 3376 PrintBytes(sizeHmacKey, hmac_key); printf("\n"); 3377 #endif 3378 3379 int current_out_size = 0; 3380 int room_left = 256; 3381 3382 // If dir is true, this is a response buffer and we add 4 bytes of 0 3383 // for some reason. 3384 if (dir) { 3385 uint32_t zero = 0; 3386 memcpy(&toHash[current_out_size], (byte*)&zero, sizeof(uint32_t)); 3387 current_out_size += sizeof(uint32_t); 3388 } 3389 ChangeEndian32((uint32_t*)&cmd, (uint32_t*)&toHash[current_out_size]); 3390 current_out_size += sizeof(uint32_t); 3391 room_left -= sizeof(uint32_t); 3392 for (int i = 0; i < numNames; i++) { 3393 memcpy(&toHash[current_out_size], names[i].name, names[i].size); 3394 current_out_size += names[i].size; 3395 room_left -= names[i].size; 3396 } 3397 memcpy(&toHash[current_out_size], parms, size_parms); 3398 current_out_size += size_parms; 3399 room_left -= size_parms; 3400 3401 #if 1 3402 printf("toHash for cpHash: "); 3403 PrintBytes(current_out_size, toHash); printf("\n"); 3404 #endif 3405 3406 // Note: current_out_size is repurposed. 3407 if (in.hash_alg_ == TPM_ALG_SHA1) { 3408 SHA1_Init(&sha1); 3409 SHA1_Update(&sha1, toHash, current_out_size); 3410 SHA1_Final(cpHash, &sha1); 3411 current_out_size = 20; 3412 } else { 3413 SHA256_Init(&sha256); 3414 SHA256_Update(&sha256, toHash, current_out_size); 3415 SHA256_Final(cpHash, &sha256); 3416 current_out_size = 32; 3417 } 3418 3419 #if 1 3420 printf("cpHash: "); 3421 PrintBytes(current_out_size, cpHash); printf("\n"); 3422 #endif 3423 3424 memcpy(toHash, cpHash, current_out_size); 3425 room_left -= current_out_size; 3426 byte* current = &toHash[current_out_size]; 3427 3428 // nonceNewer, nonceOlder, sessionAttrs 3429 memcpy(current, in.newNonce_.buffer, in.newNonce_.size); 3430 Update(in.newNonce_.size, ¤t, ¤t_out_size, &room_left); 3431 memcpy(current, in.oldNonce_.buffer, in.oldNonce_.size); 3432 Update(in.oldNonce_.size, ¤t, ¤t_out_size, &room_left); 3433 memcpy(current, &in.tpmSessionAttributes_, 1); 3434 Update(1, ¤t, ¤t_out_size, &room_left); 3435 3436 #if 1 3437 printf("Hmac in: "); 3438 PrintBytes(current_out_size, toHash); printf("\n"); 3439 #endif 3440 3441 HMAC_CTX hctx; 3442 HMAC_CTX_init(&hctx); 3443 if (in.hash_alg_ == TPM_ALG_SHA1) { 3444 HMAC_Init_ex(&hctx, hmac_key, sizeHmacKey, EVP_sha1(), nullptr); 3445 *size_hmac = 20; 3446 } else { 3447 HMAC_Init_ex(&hctx, hmac_key, sizeHmacKey, EVP_sha256(), nullptr); 3448 *size_hmac = 32; 3449 } 3450 HMAC_Update(&hctx, (const byte*)toHash, (size_t)current_out_size); 3451 HMAC_Final(&hctx, hmac, (unsigned*)size_hmac); 3452 HMAC_CTX_cleanup(&hctx); 3453 3454 #if 1 3455 printf("Hmac out: "); 3456 PrintBytes(*size_hmac, hmac); printf("\n\n"); 3457 #endif 3458 3459 return true; 3460 } 3461 3462 // sessionKey = KDFa(sessionAlg, bind.authValue||salt, ATH, 3463 // in.newNonce_.buffer, in.oldNonce_.buffer, bits) 3464 bool CalculateSessionKey(ProtectedSessionAuthInfo& in, TPM2B_DIGEST& rawSalt) { 3465 int sizeKey= SizeHash(in.hash_alg_); 3466 in.sessionKeySize_ = sizeKey; 3467 3468 #if 1 3469 printf("\nCalculateSessionKey\n"); 3470 printf("Auth value: "); 3471 PrintBytes(in.targetAuthValue_.size, in.targetAuthValue_.buffer); printf("\n"); 3472 #endif 3473 3474 string label= "ATH"; 3475 string key; 3476 string contextU; 3477 string contextV; 3478 3479 key.append((const char*)rawSalt.buffer, rawSalt.size); 3480 // For bound sessions we'd have to append the bound key auth. 3481 contextV.clear(); 3482 contextU.clear(); 3483 contextU.assign((const char*)in.newNonce_.buffer, in.newNonce_.size); 3484 contextV.assign((const char*)in.oldNonce_.buffer, in.oldNonce_.size); 3485 3486 #if 1 3487 printf("CalculateSessionKey KDFa:\n"); 3488 printf(" key : "); 3489 PrintBytes(key.size(), (byte*)key.data()); printf("\n"); 3490 printf(" label : "); 3491 PrintBytes(label.size(), (byte*)label.data()); printf("\n"); 3492 printf(" U : "); 3493 PrintBytes(contextU.size(), (byte*)contextU.data()); printf("\n"); 3494 printf(" V : "); 3495 PrintBytes(contextV.size(), (byte*)contextV.data()); printf("\n"); 3496 #endif 3497 3498 if (!KDFa(in.hash_alg_, key, label, contextU, contextV, 3499 sizeKey*NBITSINBYTE, sizeKey, in.sessionKey_)) { 3500 printf("Can't KDFa symKey\n"); 3501 return false; 3502 } 3503 3504 #if 1 3505 printf("CalculateSessionKey, key: "); 3506 PrintBytes(sizeKey, in.sessionKey_); printf("\n"); 3507 #endif 3508 return true; 3509 } 3510 3511 void RollNonces(ProtectedSessionAuthInfo& in, TPM2B_NONCE& newNonce) { 3512 memcpy(in.oldNonce_.buffer, in.newNonce_.buffer, in.newNonce_.size); 3513 in.oldNonce_.size = in.newNonce_.size; 3514 memcpy(in.newNonce_.buffer, newNonce.buffer, newNonce.size); 3515 in.newNonce_.size = newNonce.size; 3516 } 3517 3518 int CalculateandSetProtectedAuthSize(ProtectedSessionAuthInfo& authInfo, 3519 uint32_t cmd, int size_cmd_params, byte* cmd_params, 3520 byte* out, int space_left) { 3521 // TPMI_SH_AUTH_SESSION authHandle the handle for the authorization session 3522 // TPM2B_NONCE nonceCaller the caller-provided session nonce; size may be zero 3523 // TPMA_SESSION sessionAttributes the flags associated with the session 3524 // TPM2B_AUTH hmac the session HMAC digest value 3525 return sizeof(uint32_t) +sizeof(TPMI_SH_AUTH_SESSION) + 3526 sizeof(uint16_t) + authInfo.newNonce_.size + sizeof(byte) + 3527 sizeof(uint16_t) + SizeHash(authInfo.hash_alg_); 3528 } 3529 3530 int CalculateandSetProtectedAuth(ProtectedSessionAuthInfo& authInfo, 3531 uint32_t cmd, int numNames, TPM2B_NAME* names, 3532 int size_cmd_params, byte* cmd_params, byte* out, int space_left) { 3533 3534 TPM2B_NONCE newNonce; 3535 newNonce.size = authInfo.oldNonce_.size; 3536 RAND_bytes(newNonce.buffer, newNonce.size); 3537 3538 #if 1 3539 printf("CalculateandSetProtectedAuth nonce: "); 3540 PrintBytes(newNonce.size, newNonce.buffer); printf("\n"); 3541 #endif 3542 3543 RollNonces(authInfo, newNonce); 3544 3545 #if 1 3546 printf("\nAfter RollNounces in CalculateandSetProtectedAuth\n"); 3547 printf("newNonce: "); 3548 PrintBytes(authInfo.newNonce_.size, authInfo.newNonce_.buffer); printf("\n"); 3549 printf("oldNonce: "); 3550 PrintBytes(authInfo.oldNonce_.size, authInfo.oldNonce_.buffer); printf("\n"); 3551 #endif 3552 3553 int sizeHmac = SizeHash(authInfo.hash_alg_); 3554 byte hmac[128]; 3555 if (!CalculateSessionHmac(authInfo, false, cmd, numNames, names, 3556 size_cmd_params, cmd_params, &sizeHmac, hmac)) { 3557 printf("CalculateSessionHmac failed\n"); 3558 return false; 3559 } 3560 3561 // Set session auth. 3562 // TPMI_SH_AUTH_SESSION authHandle the handle for the authorization session 3563 // TPM2B_NONCE nonceCaller the caller-provided session nonce; size may be zero 3564 // TPMA_SESSION sessionAttributes the flags associated with the session 3565 // TPM2B_AUTH hmac the session HMAC digest value 3566 int space_used = 0; 3567 uint32_t sizeAuth = sizeof(uint32_t) + sizeof(uint16_t) + sizeof(byte) + 3568 sizeof(uint16_t) + sizeHmac + authInfo.oldNonce_.size; 3569 3570 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint16_t)) 3571 ChangeEndian32((uint32_t*)&sizeAuth, (uint32_t*)out); 3572 Update(sizeof(uint32_t), &out, &space_used, &space_left); 3573 3574 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint32_t)) 3575 ChangeEndian32((uint32_t*)&authInfo.sessionHandle_, (uint32_t*)out); 3576 Update(sizeof(uint32_t), &out, &space_used, &space_left); 3577 3578 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint16_t)) 3579 ChangeEndian16((uint16_t*)&authInfo.newNonce_.size, (uint16_t*)out); 3580 Update(sizeof(uint16_t), &out, &space_used, &space_left); 3581 IF_LESS_THAN_RETURN_MINUS1(space_left, authInfo.newNonce_.size) 3582 memcpy(out, authInfo.newNonce_.buffer, authInfo.newNonce_.size); 3583 Update(authInfo.newNonce_.size, &out, &space_used, &space_left); 3584 IF_LESS_THAN_RETURN_MINUS1(space_left, 1) 3585 *out = authInfo.tpmSessionAttributes_; 3586 Update(1, &out, &space_used, &space_left); 3587 3588 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeof(uint16_t)) 3589 ChangeEndian16((uint16_t*)&sizeHmac, (uint16_t*)out); 3590 Update(sizeof(uint16_t), &out, &space_used, &space_left); 3591 IF_LESS_THAN_RETURN_MINUS1(space_left, sizeHmac) 3592 memcpy(out, hmac, sizeHmac); 3593 Update(sizeHmac, &out, &space_used, &space_left); 3594 3595 return space_used; 3596 } 3597 3598 bool GetandVerifyProtectedAuth(ProtectedSessionAuthInfo& authInfo, uint32_t cmd, 3599 int numNames, TPM2B_NAME* names, 3600 int size_in, byte* in, 3601 int size_params, byte* params) { 3602 3603 #if 1 3604 printf("GetandVerifyProtectedAuth: "); 3605 PrintBytes(size_in, in); printf("\n"); 3606 printf("size_params %d: ", size_params); 3607 PrintBytes(size_params, params); printf("\n"); 3608 #endif 3609 3610 // New nonce 3611 TPM2B_NONCE newNonce; 3612 byte* current = nullptr; 3613 if (params != nullptr) 3614 current = params + size_params; 3615 else 3616 current = in + size_params; 3617 ChangeEndian16((uint16_t*)current, &newNonce.size); 3618 current += sizeof(uint16_t); 3619 memcpy(newNonce.buffer, current, newNonce.size); 3620 current += newNonce.size; 3621 byte prop = *current; 3622 current += 1; 3623 3624 TPM2B_DIGEST submitted_hmac; 3625 ChangeEndian16((uint16_t*) current, &submitted_hmac.size); 3626 current += sizeof(uint16_t); 3627 memcpy(submitted_hmac.buffer, current, submitted_hmac.size); 3628 current += submitted_hmac.size; 3629 3630 #if 1 3631 printf("NewNonce: "); 3632 PrintBytes(newNonce.size, newNonce.buffer); printf("\n"); 3633 printf("submitted: "); 3634 PrintBytes(submitted_hmac.size, submitted_hmac.buffer); printf("\n"); 3635 #endif 3636 3637 RollNonces(authInfo, newNonce); 3638 3639 #if 1 3640 printf("\nAfter RollNounces in GetandVerifyProtectedAuth\n"); 3641 printf("newNonce: "); 3642 PrintBytes(authInfo.newNonce_.size, authInfo.newNonce_.buffer); printf("\n"); 3643 printf("oldNonce: "); 3644 PrintBytes(authInfo.oldNonce_.size, authInfo.oldNonce_.buffer); printf("\n"); 3645 #endif 3646 3647 // Make sure the Hmac is right. 3648 int sizeHmac = 256; 3649 byte hmac[256]; 3650 if (!CalculateSessionHmac(authInfo, true, cmd, numNames, names, 3651 size_params, params, &sizeHmac, hmac)) { 3652 printf("Can't calculate response hmac\n"); 3653 return false; 3654 } 3655 if (submitted_hmac.size != sizeHmac || 3656 memcmp(submitted_hmac.buffer, hmac, sizeHmac) != 0) { 3657 printf("Response hmac failure\n"); 3658 return false; 3659 } 3660 return true; 3661 } 3662 3663 bool Tpm2_StartProtectedAuthSession(LocalTpm& tpm, TPM_RH tpm_obj, TPM_RH bind_obj, 3664 ProtectedSessionAuthInfo& authInfo, 3665 TPM2B_ENCRYPTED_SECRET& salt, 3666 TPM_SE session_type, TPMT_SYM_DEF& symmetric, 3667 TPMI_ALG_HASH hash_alg, TPM_HANDLE* session_handle) { 3668 byte commandBuf[2*MAX_SIZE_PARAMS]; 3669 int resp_size = MAX_SIZE_PARAMS; 3670 byte resp_buf[MAX_SIZE_PARAMS]; 3671 int size_params = 0; 3672 byte params[MAX_SIZE_PARAMS]; 3673 byte* in = params; 3674 int space_left = MAX_SIZE_PARAMS; 3675 3676 memset(params, 0, MAX_SIZE_PARAMS); 3677 3678 // Set name of bind object in the nameProtected_ variable of the 3679 // ProtectedSessionAuthInfo. 3680 authInfo.protectedHandle_ = bind_obj; 3681 3682 int n = Marshal_AuthSession_Info(tpm_obj, bind_obj, authInfo.oldNonce_, 3683 salt, session_type, symmetric, hash_alg, 3684 MAX_SIZE_PARAMS, params); 3685 IF_NEG_RETURN_FALSE(n); 3686 Update(n, &in, &size_params, &space_left); 3687 int in_size = Tpm2_SetCommand(TPM_ST_NO_SESSIONS, TPM_CC_StartAuthSession, 3688 commandBuf, size_params, params); 3689 printCommand("StartAuthSession", in_size, commandBuf); 3690 if (!tpm.SendCommand(in_size, commandBuf)) { 3691 printf("SendCommand failed\n"); 3692 return false; 3693 } 3694 if (!tpm.GetResponse(&resp_size, resp_buf)) { 3695 printf("GetResponse failed\n"); 3696 return false; 3697 } 3698 uint16_t cap = 0; 3699 uint32_t responseSize; 3700 uint32_t responseCode; 3701 Tpm2_InterpretResponse(resp_size, resp_buf, &cap, 3702 &responseSize, &responseCode); 3703 printResponse("StartAuthSession", cap, responseSize, responseCode, resp_buf); 3704 if (responseCode != TPM_RC_SUCCESS) 3705 return false; 3706 byte* current_out = resp_buf + sizeof(TPM_RESPONSE); 3707 ChangeEndian32((uint32_t*)current_out, (uint32_t*)session_handle); 3708 current_out += sizeof(uint32_t); 3709 ChangeEndian16((uint16_t*)current_out, &authInfo.newNonce_.size); 3710 current_out += sizeof(uint16_t); 3711 memcpy(authInfo.newNonce_.buffer, current_out, authInfo.newNonce_.size); 3712 current_out += authInfo.newNonce_.size; 3713 return true; 3714 } 3715 3716 bool Tpm2_DefineProtectedSpace(LocalTpm& tpm, TPM_HANDLE owner, 3717 TPMI_RH_NV_INDEX index, ProtectedSessionAuthInfo& authInfo, 3718 uint32_t attributes, uint16_t size_data) { 3719 byte commandBuf[2*MAX_SIZE_PARAMS]; 3720 int size_resp = MAX_SIZE_PARAMS; 3721 byte resp_buf[MAX_SIZE_PARAMS]; 3722 int size_params = 0; 3723 byte params_buf[MAX_SIZE_PARAMS]; 3724 int space_left = MAX_SIZE_PARAMS; 3725 byte* in = params_buf; 3726 3727 memset(commandBuf, 0, MAX_SIZE_PARAMS); 3728 memset(resp_buf, 0, MAX_SIZE_PARAMS); 3729 3730 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint32_t)) 3731 ChangeEndian32((uint32_t*)&owner, (uint32_t*)in); 3732 Update(sizeof(uint32_t), &in, &size_params, &space_left); 3733 3734 // Set auth 3735 int n = CalculateandSetProtectedAuthSize(authInfo, TPM_CC_NV_DefineSpace, 3736 0, nullptr, in, space_left); 3737 if (n < 0) { 3738 printf("CalculateandSetProtectedAuthSize failed\n"); 3739 return false; 3740 } 3741 3742 byte* auth_set = in; 3743 space_left -= n; 3744 size_params += n; 3745 in += n; 3746 3747 byte* cmd_params_place = in; 3748 uint16_t authPolicySize = 0; 3749 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)) 3750 ChangeEndian16((uint16_t*)&authPolicySize, (uint16_t*)in); 3751 Update(sizeof(uint16_t), &in, &size_params, &space_left); 3752 3753 // TPM2B_NV_PUBLIC 3754 uint16_t size_nv_area = sizeof(uint32_t) + sizeof(TPMI_RH_NV_INDEX) + 3755 sizeof(TPMI_ALG_HASH) + 2*sizeof(uint16_t) + 3756 authPolicySize; 3757 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)) 3758 ChangeEndian16((uint16_t*)&size_nv_area, (uint16_t*)in); 3759 Update(sizeof(uint16_t), &in, &size_params, &space_left); 3760 3761 // nvIndex; 3762 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint32_t)) 3763 ChangeEndian32((uint32_t*)&index, (uint32_t*)in); 3764 Update(sizeof(uint32_t), &in, &size_params, &space_left); 3765 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)) 3766 ChangeEndian16((uint16_t*)&authInfo.hash_alg_, (uint16_t*)in); 3767 Update(sizeof(uint16_t), &in, &size_params, &space_left); 3768 3769 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint32_t)) 3770 ChangeEndian32((uint32_t*)&attributes, (uint32_t*)in); 3771 Update(sizeof(uint32_t), &in, &size_params, &space_left); 3772 3773 // authPolicy size 3774 ChangeEndian16((uint16_t*)&authPolicySize, (uint16_t*)in); 3775 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)) 3776 Update(sizeof(uint16_t), &in, &size_params, &space_left); 3777 3778 // dataSize 3779 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint16_t)) 3780 ChangeEndian16((uint16_t*)&size_data, (uint16_t*)in); 3781 Update(sizeof(uint16_t), &in, &size_params, &space_left); 3782 3783 // handle name of owner is itself. 3784 TPM2B_NAME owner_name; 3785 owner_name.size = sizeof(uint32_t); 3786 ChangeEndian32((uint32_t*)&owner, (uint32_t*)owner_name.name); 3787 3788 int size_append = in - cmd_params_place; 3789 3790 // Set auth 3791 n = CalculateandSetProtectedAuth(authInfo, TPM_CC_NV_DefineSpace, 3792 1, &owner_name, size_append, cmd_params_place, 3793 auth_set, space_left); 3794 if (n < 0) { 3795 printf("CalculateandSetProtectedAuth failed\n"); 3796 return false; 3797 } 3798 3799 int in_size = Tpm2_SetCommand(TPM_ST_SESSIONS, TPM_CC_NV_DefineSpace, 3800 commandBuf, size_params, params_buf); 3801 printCommand("DefineSpace", in_size, commandBuf); 3802 if (!tpm.SendCommand(in_size, commandBuf)) { 3803 printf("SendCommand failed\n"); 3804 return false; 3805 } 3806 if (!tpm.GetResponse(&size_resp, resp_buf)) { 3807 printf("GetResponse failed\n"); 3808 return false; 3809 } 3810 uint16_t cap = 0; 3811 uint32_t responseSize; 3812 uint32_t responseCode; 3813 Tpm2_InterpretResponse(size_resp, resp_buf, &cap, 3814 &responseSize, &responseCode); 3815 printResponse("Definespace", cap, responseSize, responseCode, resp_buf); 3816 if (responseCode != TPM_RC_SUCCESS) 3817 return false; 3818 3819 int size_resp_params = 0; 3820 byte* current_in = resp_buf + sizeof(TPM_RESPONSE); 3821 ChangeEndian32((uint32_t*)current_in, (uint32_t*)&size_resp_params); 3822 byte* resp_params = current_in + sizeof(uint32_t); 3823 3824 TPM2B_NAME no_name; 3825 no_name.size = sizeof(uint32_t); 3826 memset(no_name.name, 0, no_name.size); 3827 if (!GetandVerifyProtectedAuth(authInfo, TPM_CC_NV_DefineSpace, 0, 3828 &no_name, responseSize - sizeof(TPM_RESPONSE), 3829 resp_buf + sizeof(TPM_RESPONSE), 3830 size_resp_params, resp_params)) { 3831 printf("GetandVerifyProtectedAuth failed\n"); 3832 return false; 3833 } 3834 return true; 3835 } 3836 3837 bool Tpm2_IncrementProtectedNv(LocalTpm& tpm, TPMI_RH_NV_INDEX index, 3838 ProtectedSessionAuthInfo& authInfo) { 3839 byte commandBuf[2*MAX_SIZE_PARAMS]; 3840 int size_resp = MAX_SIZE_PARAMS; 3841 byte resp_buf[MAX_SIZE_PARAMS]; 3842 int size_params = 0; 3843 byte params_buf[MAX_SIZE_PARAMS]; 3844 int space_left = MAX_SIZE_PARAMS; 3845 byte* in = params_buf; 3846 3847 memset(commandBuf, 0, MAX_SIZE_PARAMS); 3848 memset(resp_buf, 0, MAX_SIZE_PARAMS); 3849 3850 // handle 3851 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint32_t)) 3852 ChangeEndian32((uint32_t*)&index, (uint32_t*)in); 3853 Update(sizeof(uint32_t), &in, &size_params, &space_left); 3854 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint32_t)) 3855 ChangeEndian32((uint32_t*)&index, (uint32_t*)in); 3856 Update(sizeof(uint32_t), &in, &size_params, &space_left); 3857 3858 TPM2B_NAME nv_name[2]; 3859 if (!CalculateNvName(authInfo, index, 3860 authInfo.hash_alg_, authInfo.protectedAttributes_, 3861 authInfo.protectedSize_, true, nv_name[0].name)) { 3862 } 3863 3864 // Fix this 3865 nv_name[0].size = SizeHash(authInfo.hash_alg_) + sizeof(uint16_t); 3866 if (!CalculateNvName(authInfo, index, 3867 authInfo.hash_alg_, authInfo.protectedAttributes_, 3868 authInfo.protectedSize_, true, nv_name[1].name)) { 3869 } 3870 3871 // Fix this 3872 nv_name[1].size = SizeHash(authInfo.hash_alg_) + sizeof(uint16_t); 3873 int n = CalculateandSetProtectedAuthSize(authInfo, TPM_CC_NV_Increment, 3874 0, nullptr, in, space_left); 3875 if (n < 0) { 3876 printf("CalculateandSetProtectedAuth failed\n"); 3877 return false; 3878 } 3879 byte* auth_set = in; 3880 space_left -= n; 3881 size_params += n; 3882 in += n; 3883 3884 // Set auth 3885 n = CalculateandSetProtectedAuth(authInfo, TPM_CC_NV_Increment, 3886 2, nv_name, 0, nullptr, auth_set, space_left); 3887 if (n < 0) { 3888 printf("CalculateandSetProtectedAuth failed\n"); 3889 return false; 3890 } 3891 3892 int in_size = Tpm2_SetCommand(TPM_ST_SESSIONS, TPM_CC_NV_Increment, 3893 commandBuf, size_params, params_buf); 3894 printCommand("IncrementProtectedNv", in_size, commandBuf); 3895 if (!tpm.SendCommand(in_size, commandBuf)) { 3896 printf("SendCommand failed\n"); 3897 return false; 3898 } 3899 if (!tpm.GetResponse(&size_resp, resp_buf)) { 3900 printf("GetResponse failed\n"); 3901 return false; 3902 } 3903 uint16_t cap = 0; 3904 uint32_t responseSize; 3905 uint32_t responseCode; 3906 Tpm2_InterpretResponse(size_resp, resp_buf, &cap, &responseSize, &responseCode); 3907 printResponse("IncrementProtectedNv", cap, responseSize, responseCode, resp_buf); 3908 if (responseCode != TPM_RC_SUCCESS) 3909 return false; 3910 printf("TPM_CC_NV_Increment response size: %d\n", responseSize); 3911 3912 int size_resp_params = 0; 3913 byte* resp_params = resp_buf + sizeof(TPM_RESPONSE) + sizeof(uint32_t); 3914 3915 if (!GetandVerifyProtectedAuth(authInfo, TPM_CC_NV_Increment, 0, 3916 nv_name, responseSize - sizeof(TPM_RESPONSE), 3917 resp_buf + sizeof(TPM_RESPONSE), 3918 size_resp_params, resp_params)) { 3919 printf("GetandVerifyProtectedAuth failed\n"); 3920 return false; 3921 } 3922 return true; 3923 } 3924 3925 bool Tpm2_ReadProtectedNv(LocalTpm& tpm, TPMI_RH_NV_INDEX index, 3926 ProtectedSessionAuthInfo& authInfo, 3927 uint16_t* size, byte* data) { 3928 byte commandBuf[2*MAX_SIZE_PARAMS]; 3929 int size_resp = MAX_SIZE_PARAMS; 3930 byte resp_buf[MAX_SIZE_PARAMS]; 3931 memset(resp_buf, 0, MAX_SIZE_PARAMS); 3932 int size_params = 0; 3933 byte params_buf[MAX_SIZE_PARAMS]; 3934 int space_left = MAX_SIZE_PARAMS; 3935 byte* in = params_buf; 3936 3937 memset(commandBuf, 0, MAX_SIZE_PARAMS); 3938 memset(params_buf, 0, MAX_SIZE_PARAMS); 3939 3940 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint32_t)) 3941 ChangeEndian32((uint32_t*)&index, (uint32_t*)in); 3942 Update(sizeof(uint32_t), &in, &size_params, &space_left); 3943 IF_LESS_THAN_RETURN_FALSE(space_left, sizeof(uint32_t)) 3944 ChangeEndian32((uint32_t*)&index, (uint32_t*)in); 3945 Update(sizeof(uint32_t), &in, &size_params, &space_left); 3946 byte* auth_set = in; 3947 3948 // Set Hmac auth 3949 TPM2B_NAME nv_name[2]; 3950 if (!CalculateNvName(authInfo, index, 3951 authInfo.hash_alg_, authInfo.protectedAttributes_, 3952 authInfo.protectedSize_, true, nv_name[0].name)) { 3953 } 3954 // Fix this 3955 nv_name[0].size = SizeHash(authInfo.hash_alg_) + sizeof(uint16_t); 3956 if (!CalculateNvName(authInfo, index, 3957 authInfo.hash_alg_, authInfo.protectedAttributes_, 3958 authInfo.protectedSize_, true, nv_name[1].name)) { 3959 } 3960 // Fix this 3961 nv_name[1].size = SizeHash(authInfo.hash_alg_) + sizeof(uint16_t); 3962 3963 int n = CalculateandSetProtectedAuthSize(authInfo, TPM_CC_NV_Increment, 3964 0, nullptr, in, space_left); 3965 if (n < 0) { 3966 printf("CalculateandSetProtectedAuth failed\n"); 3967 return false; 3968 } 3969 space_left -= n; 3970 size_params += n; 3971 in += n; 3972 byte* cmd_params_place = in; 3973 3974 // parameters 3975 uint16_t offset = 0; 3976 IF_NEG_RETURN_FALSE(n); 3977 ChangeEndian16((uint16_t*)size, (uint16_t*)in); 3978 Update(sizeof(uint16_t), &in, &size_params, &space_left); 3979 IF_NEG_RETURN_FALSE(n); 3980 ChangeEndian16((uint16_t*)&offset, (uint16_t*)in); 3981 Update(sizeof(uint16_t), &in, &size_params, &space_left); 3982 3983 // Set auth 3984 n = CalculateandSetProtectedAuth(authInfo, TPM_CC_NV_Read, 3985 2, nv_name, in - cmd_params_place, cmd_params_place, 3986 auth_set, space_left); 3987 if (n < 0) { 3988 printf("CalculateSessionHmac failed\n"); 3989 return false; 3990 } 3991 3992 int in_size = Tpm2_SetCommand(TPM_ST_SESSIONS, TPM_CC_NV_Read, 3993 commandBuf, size_params, params_buf); 3994 printCommand("ReadProtectedNv", in_size, commandBuf); 3995 if (!tpm.SendCommand(in_size, commandBuf)) { 3996 printf("SendCommand failed\n"); 3997 return false; 3998 } 3999 if (!tpm.GetResponse(&size_resp, resp_buf)) { 4000 printf("GetResponse failed\n"); 4001 return false; 4002 } 4003 uint16_t cap = 0; 4004 uint32_t responseSize; 4005 uint32_t responseCode; 4006 Tpm2_InterpretResponse(size_resp, resp_buf, &cap, 4007 &responseSize, &responseCode); 4008 printResponse("ReadNv", cap, responseSize, responseCode, resp_buf); 4009 if (responseCode != TPM_RC_SUCCESS) 4010 return false; 4011 4012 int size_resp_params = 0; 4013 byte* current_in = resp_buf + sizeof(TPM_RESPONSE); 4014 ChangeEndian32((uint32_t*)current_in, (uint32_t*)&size_resp_params); 4015 byte* resp_params = current_in + sizeof(uint32_t); 4016 4017 if (!GetandVerifyProtectedAuth(authInfo, TPM_CC_NV_Read, 0, 4018 nv_name, responseSize - sizeof(TPM_RESPONSE), 4019 resp_buf + sizeof(TPM_RESPONSE), 4020 size_resp_params, resp_params)) { 4021 printf("GetandVerifyProtectedAuth failed\n"); 4022 return false; 4023 } 4024 4025 ChangeEndian16((uint16_t*)resp_params, (uint16_t*)size); 4026 resp_params += sizeof(uint16_t); 4027 memcpy(data, resp_params, *size); 4028 return true; 4029 } 4030