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*)&quote_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), &current, &current_out_size, &room_left);
  3283    ChangeEndian16(&nv_hash_alg, (uint16_t*)current);
  3284    Update(sizeof(uint16_t), &current, &current_out_size, &room_left);
  3285    ChangeEndian32(&new_attributes, (uint32_t*)current);
  3286    Update(sizeof(uint32_t), &current, &current_out_size, &room_left);
  3287    ChangeEndian16(&zero, (uint16_t*)current);
  3288    Update(sizeof(uint16_t), &current, &current_out_size, &room_left);
  3289    ChangeEndian16(&data_size, (uint16_t*)current);
  3290    Update(sizeof(uint16_t), &current, &current_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, &current, &current_out_size, &room_left);
  3431    memcpy(current, in.oldNonce_.buffer, in.oldNonce_.size);
  3432    Update(in.oldNonce_.size, &current, &current_out_size, &room_left);
  3433    memcpy(current, &in.tpmSessionAttributes_, 1);
  3434    Update(1, &current, &current_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