github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/src/tpm2/tpm2_util.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  
     9  #include <tpm20.h>
    10  #include <tpm2_lib.h>
    11  #include <gflags/gflags.h>
    12  
    13  #include <openssl_helpers.h>
    14  
    15  #include <openssl/rsa.h>
    16  #include <openssl/x509.h>
    17  #include <openssl/ssl.h>
    18  #include <openssl/evp.h>
    19  #include <openssl/asn1.h>
    20  #include <openssl/err.h>
    21  #include <openssl/aes.h>
    22  #include <openssl/hmac.h>
    23  #include <openssl/rand.h>
    24  
    25  //
    26  // Copyright 2015 Google Corporation, All Rights Reserved.
    27  //
    28  // Licensed under the Apache License, Version 2.0 (the "License");
    29  // you may not use this file except in compliance with the License.
    30  // You may obtain a copy of the License at
    31  //     http://www.apache.org/licenses/LICENSE-2.0
    32  // or in the the file LICENSE-2.0.txt in the top level sourcedirectory
    33  // Unless required by applicable law or agreed to in writing, software
    34  // distributed under the License is distributed on an "AS IS" BASIS,
    35  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    36  // See the License for the specific language governing permissions and
    37  // limitations under the License
    38  //
    39  // Portions of this code were derived TPM2.0-TSS published
    40  // by Intel under the license set forth in intel_license.txt
    41  // and downloaded on or about August 6, 2015.
    42  // Portions of this code were derived tboot published
    43  // by Intel under the license set forth in intel_license.txt
    44  // and downloaded on or about August 6, 2015.
    45  // Portions of this code were derived from the crypto utility
    46  // published by John Manferdelli under the Apache 2.0 license.
    47  // See github.com/jlmucb/crypto.
    48  // File: tpm2_util.cc
    49  
    50  
    51  // Calling sequence
    52  // tpm2_util.exe --Commmand=command 
    53  
    54  using std::string;
    55  
    56  DEFINE_string(command, "", "command");
    57  DEFINE_int32(numbytes, 16, "numbytes");
    58  DEFINE_int32(num_param, 16, "integer parameter");
    59  DEFINE_string(password, "password", "password");
    60  DEFINE_string(authString, "", "authString");
    61  DEFINE_string(parentAuth, "", "parent auth String");
    62  DEFINE_string(handle, "", "handle");
    63  DEFINE_int32(pcr_num, -1, "integer parameter");
    64  DEFINE_int32(index, -1, "nv index");
    65  DEFINE_int32(nv_slot, 1000, "nv slot");
    66  DEFINE_int32(nv_size, -1, "nv size");
    67  DEFINE_string(parent_public_file, "", "parent public area");
    68  DEFINE_string(public_file, "", "public area");
    69  DEFINE_string(private_file, "", "private public area");
    70  DEFINE_string(creation_data_file, "", "private public area");
    71  DEFINE_string(save_context_file, "", "save(d) context area");
    72  DEFINE_string(decrypt, "", "decrypt flag");
    73  DEFINE_uint64(startHandle, 0x80000000, "start handle range");
    74  
    75  #ifndef GFLAGS_NS
    76  #define GFLAGS_NS google
    77  #endif
    78  
    79  int num_tpmutil_ops = 28;
    80  std::string tpmutil_ops[] = {
    81      "--command=Startup",
    82      "--command=Shutdown",
    83      "--command=GetCapabilities",
    84      "--command=Flushall",
    85      "--command=GetRandom",
    86      "--command=ReadClock",
    87      "--command=CreatePrimary",
    88      "--command=Load",
    89      "--command=Save",
    90      "--command=CreateKey",
    91      "--command=ReadPcr",
    92      "--command=Unseal",
    93      "--command=Quote",
    94      "--command=LoadContext",
    95      "--command=SaveContext",
    96      "--command=FlushContext",
    97      "--command=ReadNv",
    98      "--command=WriteNv",
    99      "--command=DefineSpace",
   100      "--command=UndefineSpace",
   101      "--command=SealCombinedTest",
   102      "--command=QuoteCombinedTest",
   103      "--command=DictionaryAttackLockReset",
   104      "--command=KeyCombinedTest",
   105      "--command=NvCombinedTest",
   106      "--command=ContextCombinedTest",
   107      "--command=EndorsementCombinedTest",
   108      "--command=NvCombinedSessionTest",
   109  };
   110  
   111  // standard buffer size
   112  #define MAX_SIZE_PARAMS 4096
   113  
   114  // Combined tests
   115  bool Tpm2_SealCombinedTest(LocalTpm& tpm, int pcr_num);
   116  bool Tpm2_QuoteCombinedTest(LocalTpm& tpm, int pcr_num);
   117  bool Tpm2_KeyCombinedTest(LocalTpm& tpm, int pcr_num);
   118  bool Tpm2_NvCombinedTest(LocalTpm& tpm);
   119  bool Tpm2_NvCombinedSessionTest(LocalTpm& tpm);
   120  bool Tpm2_ContextCombinedTest(LocalTpm& tpm);
   121  bool Tpm2_EndorsementCombinedTest(LocalTpm& tpm);
   122  
   123  void PrintOptions() {
   124    printf("Permitted operations:\n");
   125    for (int i = 0; i < num_tpmutil_ops; i++) {
   126      printf("  tpmutil.exe %s\n", tpmutil_ops[i].c_str());
   127    }
   128    return;
   129  }
   130  
   131  int main(int an, char** av) {
   132    LocalTpm tpm;
   133  
   134    GFLAGS_NS::ParseCommandLineFlags(&an, &av, true);
   135    if (!tpm.OpenTpm("/dev/tpm0")) {
   136      printf("Can't open tpm\n");
   137      return 1;
   138    }
   139  
   140    if (FLAGS_command == "GetCapabilities") {
   141      int size = 512;
   142      byte buf[512];
   143      if (!Tpm2_GetCapability(tpm, TPM_CAP_TPM_PROPERTIES, FLAGS_startHandle,
   144                              &size, buf)) {
   145        printf("Tpm2_GetCapability failed\n");
   146      }
   147      PrintCapabilities(size, buf);
   148    } else if (FLAGS_command == "Startup") {
   149      if (!Tpm2_Startup(tpm)) {
   150        printf("Tpm2_Startup failed\n");
   151      }
   152    } else if (FLAGS_command == "Shutdown") {
   153      if (!Tpm2_Shutdown(tpm)) {
   154        printf("Tpm2_Shutdown failed\n");
   155      }
   156    } else if (FLAGS_command == "GetRandom") {
   157      byte buf[256];
   158  
   159      if (FLAGS_numbytes >256) {
   160        printf("Can only get up to 256 bytes\n");
   161        goto done;
   162      }
   163      memset(buf, 0, 256);
   164      if (Tpm2_GetRandom(tpm, FLAGS_numbytes, buf)) {
   165        printf("Random bytes: ");
   166        PrintBytes(FLAGS_numbytes, buf);
   167        printf("\n");
   168      } else {
   169        printf("GetRandom failed\n");
   170      }
   171    } else if (FLAGS_command == "ReadClock") {
   172      uint64_t current_time, current_clock;
   173      if (Tpm2_ReadClock(tpm, &current_time, &current_clock)) {
   174        printf("time: %lx %lx\n\n", current_time, current_clock);
   175      } else {
   176        printf("ReadClock failed\n");
   177      }
   178    } else if (FLAGS_command == "CreatePrimary") {
   179  #if 0
   180      TPM_HANDLE handle;
   181      TPM2B_PUBLIC pub_out;
   182      TPML_PCR_SELECTION pcrSelect;
   183      InitSinglePcrSelection(FLAGS_pcr_num, TPM_ALG_SHA1, &pcrSelect);
   184      bool sign = true;
   185      if (FLAGS_decrypt.size() > 0)
   186        sign = false;
   187      if (Tpm2_CreatePrimary(tpm, TPM_RH_OWNER, FLAGS_authString,
   188                             pcrSelect, sign,
   189                             &handle, &pub_out)) {
   190        printf("Tpm2_CreatePrimary succeeds\n");
   191        printf("Public handle: %08x\n", (uint32_t)handle);
   192        printf("type: %04x\n", pub_out.publicArea.type);
   193        printf("nameAlg: %04x\n", pub_out.publicArea.nameAlg);
   194        printf("Attributes: %08x\n", *(uint32_t*)
   195                  &pub_out.publicArea.objectAttributes);
   196        printf("Algorithm: %08x\n",
   197          pub_out.publicArea.parameters.rsaDetail.symmetric.algorithm);
   198        printf("keySize: %04x\n", pub_out.publicArea.parameters.rsaDetail.keyBits);
   199        printf("Modulus: ");
   200        PrintBytes(pub_out.publicArea.unique.rsa.size,
   201                  pub_out.publicArea.unique.rsa.buffer);
   202        printf("\n");
   203      } else {
   204        printf("CreatePrimary failed\n");
   205      }
   206  #endif
   207    } else if (FLAGS_command == "Load") {
   208      TPM_HANDLE parent_handle = 0x80000000;
   209      TPM_HANDLE new_handle;
   210      TPM2B_NAME name;
   211      if (FLAGS_handle.size() >0 ) {
   212        long unsigned t;
   213        t = std::stoul(FLAGS_handle.c_str(), nullptr, 16);
   214        parent_handle = (TPM_HANDLE) t;
   215      } 
   216      int size_public = 4096;
   217      byte inPublic[4096];
   218      int size_private = 4096;
   219      byte inPrivate[4096];
   220      bool ok = true;
   221      if (!ReadFileIntoBlock(FLAGS_public_file, &size_public, inPublic)) {
   222        printf("Can't read public block\n");
   223        ok = false;
   224      }
   225      if (!ReadFileIntoBlock(FLAGS_private_file, &size_private, inPrivate)) {
   226        printf("Can't read public block\n");
   227        ok = false;
   228      }
   229      if (ok && Tpm2_Load(tpm, parent_handle, FLAGS_parentAuth, size_public, inPublic,
   230                          size_private, inPrivate, &new_handle, &name)) {
   231        printf("Load succeeded, new handle: %08x\n", new_handle);
   232      } else {
   233        printf("Load failed\n");
   234      }
   235    } else if (FLAGS_command == "Save") {
   236      if (Tpm2_Save(tpm)) {
   237        printf("Save succeeded\n");
   238      } else {
   239        printf("Save failed\n");
   240      }
   241    } else if (FLAGS_command == "ReadPcr") {
   242      uint32_t updateCounter;
   243      TPML_PCR_SELECTION pcrSelectOut;
   244      TPML_DIGEST values;
   245      if (Tpm2_ReadPcr(tpm, FLAGS_pcr_num, &updateCounter,
   246                       &pcrSelectOut, &values)) {
   247        printf("ReadPcr succeeds, updateCounter: %08x\n", updateCounter);
   248        printf("Pcr %d :", FLAGS_pcr_num);
   249        PrintBytes(values.digests[0].size, values.digests[0].buffer);
   250        printf("\n");
   251      } else {
   252        printf("ReadPcr failed\n");
   253      }
   254    } else if (FLAGS_command == "CreateKey") {
   255  #if 0
   256      TPM_HANDLE parent_handle;
   257  
   258      TPM2B_CREATION_DATA creation_out;
   259      TPM2B_DIGEST digest_out;
   260      TPMT_TK_CREATION creation_ticket;
   261      int size_public = 4096;
   262      byte out_public[4096];
   263      int size_private = 4096;
   264      byte out_private[4096];
   265  
   266      parent_handle = 0x80000000;
   267      if (FLAGS_handle.size() > 0 ) {
   268        long unsigned t;
   269        t = std::stoul(FLAGS_handle.c_str(), nullptr, 16);
   270        parent_handle = (TPM_HANDLE) t;
   271      } 
   272      TPML_PCR_SELECTION pcrSelect;
   273      InitSinglePcrSelection(FLAGS_pcr_num, TPM_ALG_SHA1, &pcrSelect);
   274      bool sign = true;
   275      if (FLAGS_decrypt.size() > 0)
   276        sign = false;
   277      if (Tpm2_CreateKey(tpm, parent_handle, FLAGS_parentAuth,
   278                      FLAGS_authString, pcrSelect,
   279                      sign, false, &size_public, out_public,
   280                      &size_private, out_private,
   281                      &creation_out, &digest_out, &creation_ticket)) {
   282        printf("CreateKey succeeded\n");
   283        printf("Public (%d): ", size_public);
   284        PrintBytes(size_public, out_public);
   285        printf("\n");
   286        printf("Private (%d): ", size_private);
   287        PrintBytes(size_private, out_private);
   288        printf("\n");
   289        if (!WriteFileFromBlock(FLAGS_public_file, 
   290                                size_public, out_public)) {
   291          printf("Can't write %s, CreateKey failed\n", FLAGS_private_file.c_str());
   292        } else if (!WriteFileFromBlock(FLAGS_private_file,
   293                                       size_private, out_private)){ 
   294          printf("Can't write %s\n", FLAGS_private_file.c_str());
   295        } else {
   296          printf("CreateKey succeeded\n");
   297        }
   298      }
   299      printf("CreateKey failed\n");
   300  #endif
   301    } else if (FLAGS_command == "Unseal") {
   302  #if 0
   303      TPM_HANDLE item_handle = 0;
   304      int out_size = 1024;
   305      byte out[1024];
   306      int size_digest = 0;
   307      byte digest[64];
   308      if (Tpm2_Unseal(tpm, item_handle, FLAGS_parentAuth,
   309                      pcrSelector, TPM_ALG_SHA1, size_digest, digest,
   310                      &out_size, out)) {
   311        printf("Unseal succeeded: ");
   312        PrintBytes(out_size, out);
   313        printf("\n");
   314      } else {
   315        printf("Unseal failed\n");
   316      }
   317  #endif
   318    } else if (FLAGS_command == "Quote") {
   319  #if 0
   320      int quote_size = 1024;
   321      byte quote[1024];
   322      TPM_HANDLE signingHandle = 0;
   323      TPMT_SIG_SCHEME scheme;
   324      TPML_PCR_SELECTION pcr_selection;
   325      int attest_size = 1024;
   326      byte attest[1024];
   327      int sig_size = 1024;
   328      byte sig[1024];
   329      if (Tpm2_Quote(tpm, signingHandle, quote_size, quote, scheme, pcr_selection,
   330                 &attest_size, attest, &sig_size, sig)) {
   331        printf("Quote succeeded\n");
   332      } else {
   333        printf("Quote failed\n");
   334      }
   335  #endif
   336    } else if (FLAGS_command == "UndefineSpace") {
   337      TPM_HANDLE nv_handle = GetNvHandle(FLAGS_nv_slot);
   338      
   339      if (FLAGS_nv_slot < 0) {
   340        printf("Invalid index\n");
   341      } else if (!Tpm2_UndefineSpace(tpm, TPM_RH_OWNER, nv_handle)) {
   342        printf("UndefineSpace succeeded\n");
   343      } else {
   344        printf("UndefineSpace failed\n");
   345      }
   346    } else if (FLAGS_command == "DefineSpace") {
   347      TPM_HANDLE nv_handle = GetNvHandle(FLAGS_nv_slot);
   348      uint16_t size_data = (uint16_t) FLAGS_nv_size;
   349      if (Tpm2_DefineSpace(tpm, TPM_RH_OWNER, nv_handle, FLAGS_authString,
   350                           0, nullptr, NV_AUTHWRITE | NV_AUTHREAD, size_data)) {
   351        printf("DefineSpace succeeded\n");
   352      } else {
   353        printf("DefineSpace failed\n");
   354      }
   355    } else if (FLAGS_command == "LoadContext") {
   356      int size = 4096;
   357      byte saveArea[4096];
   358      memset(saveArea, 0, 4096);
   359      TPM_HANDLE handle = 0;
   360  
   361      if (!ReadFileIntoBlock(FLAGS_save_context_file, &size, saveArea)) {
   362          printf("Can't read %s, LoadContext failed\n", FLAGS_save_context_file.c_str());
   363      } else if (Tpm2_LoadContext(tpm, size, saveArea, &handle)) {
   364        printf("LoadContext succeeded\n");
   365      } else {
   366        printf("LoadContext failed\n");
   367      }
   368    } else if (FLAGS_command == "SaveContext") {
   369      uint16_t size = 4096;
   370      byte saveArea[4096];
   371      memset(saveArea, 0, 4096);
   372  
   373      TPM_HANDLE handle = 0x80000000;
   374      if (FLAGS_handle.size() > 0 ) {
   375        long unsigned t;
   376        t = std::stoul(FLAGS_handle.c_str(), nullptr, 16);
   377        handle = (TPM_HANDLE) t;
   378      } else if (Tpm2_SaveContext(tpm, handle, &size, saveArea)) {
   379        if (!WriteFileFromBlock(FLAGS_save_context_file, size, saveArea)) {
   380          printf("Can't write %s, SaveContext failed\n", FLAGS_save_context_file.c_str());
   381        } else { 
   382          printf("SaveContext successful\n");
   383        }
   384      } else {
   385        printf("SaveContext failed\n");
   386      }
   387    } else if (FLAGS_command == "FlushContext") {
   388      TPM_HANDLE handle = 0x80000000;
   389      if (FLAGS_handle.size() >0 ) {
   390        long unsigned t;
   391        t = std::stoul(FLAGS_handle.c_str(), nullptr, 16);
   392        handle = (TPM_HANDLE) t;
   393      } 
   394      if (Tpm2_FlushContext(tpm, handle)) {
   395        printf("FlushContext succeeded\n");
   396      } else {
   397        printf("FlushContext failed\n");
   398      }
   399    } else if (FLAGS_command == "Tpm2_Read_Nv") {
   400      TPMI_RH_NV_INDEX index = (TPMI_RH_NV_INDEX) FLAGS_index;
   401      uint16_t size_data = 16;
   402      byte data[1024];
   403      if (Tpm2_ReadNv(tpm, index, FLAGS_authString, &size_data, data)) {
   404        printf("Tpm2_Read_Nv succeeded\n");
   405        PrintBytes(size_data, data);
   406        printf("\n");
   407      } else {
   408        printf("Tpm2_Read_Nv failed\n");
   409      }
   410    } else if (FLAGS_command == "Tpm2_Write_Nv") {
   411      TPMI_RH_NV_INDEX index = (TPMI_RH_NV_INDEX) FLAGS_index;
   412      int size_data = 0;
   413      byte data[1024];
   414      if (Tpm2_WriteNv(tpm, index, FLAGS_authString, size_data, data)) {
   415        printf("Tpm2_Write_Nv succeeded\n");
   416      } else {
   417        printf("Tpm2_Write_Nv failed\n");
   418      }
   419    } else if (FLAGS_command == "Flushall") {
   420      if (Tpm2_Flushall(tpm, FLAGS_startHandle)) {
   421        printf("Flushall succeeded\n");
   422      } else {
   423        printf("Flushall failed\n");
   424      }
   425    } else if (FLAGS_command == "KeyCombinedTest") {
   426      if (Tpm2_KeyCombinedTest(tpm, FLAGS_pcr_num)) {
   427        printf("Tpm2_KeyCombinedTest succeeded\n");
   428      } else {
   429        printf("Tpm2_KeyCombinedTest failed\n");
   430      }
   431    } else if (FLAGS_command == "SealCombinedTest") {
   432      if (Tpm2_SealCombinedTest(tpm, FLAGS_pcr_num)) {
   433        printf("SealCombinedTest succeeded\n");
   434      } else {
   435        printf("SealCombinedTest failed\n");
   436      }
   437    } else if (FLAGS_command == "QuoteCombinedTest") {
   438      if (Tpm2_QuoteCombinedTest(tpm, FLAGS_pcr_num)) {
   439        printf("QuoteCombinedTest succeeded\n");
   440      } else {
   441        printf("QuoteCombinedTest failed\n");
   442      }
   443    } else if (FLAGS_command == "NvCombinedTest") {
   444      if (Tpm2_NvCombinedTest(tpm)) {
   445        printf("NvCombinedTest succeeded\n");
   446      } else {
   447        printf("NvCombinedTest failed\n");
   448      }
   449    } else if (FLAGS_command == "NvCombinedSessionTest") {
   450      if (Tpm2_NvCombinedSessionTest(tpm)) {
   451        printf("NvCombinedSessionTest succeeded\n");
   452      } else {
   453        printf("NvCombinedSessionTest failed\n");
   454      }
   455    } else if (FLAGS_command == "ContextCombinedTest") {
   456      if (Tpm2_ContextCombinedTest(tpm)) {
   457        printf("ContextCombinedTest succeeded\n");
   458      } else {
   459        printf("ContextCombinedTest failed\n");
   460      }
   461    } else if (FLAGS_command == "EndorsementCombinedTest") {
   462      if (Tpm2_EndorsementCombinedTest(tpm)) {
   463        printf("EndorsementCombinedTest succeeded\n");
   464      } else {
   465        printf("EndorsementCombinedTest failed\n");
   466      }
   467    } else if (FLAGS_command == "DictionaryAttackLockReset") {
   468      if (Tpm2_DictionaryAttackLockReset(tpm)) {
   469        printf("Tpm2_DictionaryAttackLockReset succeeded\n");
   470      } else {
   471        printf("Tpm2_DictionaryAttackLockReset failed\n");
   472      }
   473    } else {
   474      printf("Invalid command\n");
   475      PrintOptions();
   476    }
   477  done:
   478    tpm.CloseTpm();
   479  }
   480  
   481  // Combined tests
   482  
   483  bool Tpm2_EndorsementCombinedTest(LocalTpm& tpm) {
   484    string authString("01020304");
   485    string parentAuth("01020304");
   486    string emptyAuth;
   487  
   488    TPM_HANDLE ekHandle;
   489    TPM2B_PUBLIC pub_out;
   490    TPM2B_NAME pub_name;
   491    TPM2B_NAME qualified_pub_name;
   492    uint16_t pub_blob_size = 1024;
   493    byte pub_blob[1024];
   494  
   495    TPML_PCR_SELECTION pcrSelect;
   496    memset((void*)&pcrSelect, 0, sizeof(TPML_PCR_SELECTION));
   497  
   498    // TPM_RH_ENDORSEMENT
   499    TPMA_OBJECT primary_flags;
   500    *(uint32_t*)(&primary_flags) = 0;
   501    primary_flags.fixedTPM = 1;
   502    primary_flags.fixedParent = 1;
   503    primary_flags.sensitiveDataOrigin = 1;
   504    primary_flags.userWithAuth = 1;
   505    primary_flags.decrypt = 1;
   506    primary_flags.restricted = 1;
   507  
   508    if (Tpm2_CreatePrimary(tpm, TPM_RH_ENDORSEMENT, emptyAuth, pcrSelect,
   509                           TPM_ALG_RSA, TPM_ALG_SHA256, primary_flags,
   510                           TPM_ALG_AES, 128, TPM_ALG_CFB, TPM_ALG_NULL,
   511                           2048, 0x010001, &ekHandle, &pub_out)) {
   512      printf("CreatePrimary succeeded parent: %08x\n", ekHandle);
   513    } else {
   514      printf("CreatePrimary failed\n");
   515      return false;
   516    }
   517    if (Tpm2_ReadPublic(tpm, ekHandle, &pub_blob_size, pub_blob,
   518                        &pub_out, &pub_name, &qualified_pub_name)) {
   519      printf("ReadPublic succeeded\n");
   520    } else {
   521      printf("ReadPublic failed\n");
   522      return false;
   523    }
   524    printf("Public blob: ");
   525    PrintBytes(pub_blob_size, pub_blob);
   526    printf("\n");
   527    printf("Name: ");
   528    PrintBytes(pub_name.size, pub_name.name);
   529    printf("\n");
   530    printf("Qualified name: ");
   531    PrintBytes(qualified_pub_name.size, qualified_pub_name.name);
   532    printf("\n");
   533  
   534    TPM_HANDLE parentHandle;
   535    TPM_HANDLE activeHandle;
   536    TPM2B_PUBLIC parent_pub_out;
   537    TPML_PCR_SELECTION parent_pcrSelect;
   538    InitSinglePcrSelection(7, TPM_ALG_SHA1, &parent_pcrSelect);
   539  
   540    TPMA_OBJECT parent_flags;
   541    *(uint32_t*)(&parent_flags) = 0;
   542    parent_flags.fixedTPM = 1;
   543    parent_flags.fixedParent = 1;
   544    parent_flags.sensitiveDataOrigin = 1;
   545    parent_flags.userWithAuth = 1;
   546    parent_flags.decrypt = 1;
   547    parent_flags.restricted = 1;
   548  
   549    if (Tpm2_CreatePrimary(tpm, TPM_RH_OWNER, authString, parent_pcrSelect,
   550                           TPM_ALG_RSA, TPM_ALG_SHA256, parent_flags,
   551                           TPM_ALG_AES, 128, TPM_ALG_CFB, TPM_ALG_NULL,
   552                           1024, 0x010001,
   553                           &parentHandle, &parent_pub_out)) {
   554      printf("CreatePrimary succeeded\n");
   555    } else {
   556      printf("CreatePrimary failed\n");
   557      return false;
   558    }
   559    TPM2B_CREATION_DATA creation_out;
   560    TPM2B_DIGEST digest_out;
   561    TPMT_TK_CREATION creation_ticket;
   562    int size_public = MAX_SIZE_PARAMS;
   563    byte out_public[MAX_SIZE_PARAMS];
   564    int size_private = MAX_SIZE_PARAMS;
   565    byte out_private[MAX_SIZE_PARAMS];
   566  
   567    memset((void*)&pub_out, 0, sizeof(TPM2B_PUBLIC));
   568  
   569    TPMA_OBJECT active_flags;
   570    *(uint32_t*)(&active_flags) = 0;
   571    active_flags.fixedTPM = 1;
   572    active_flags.fixedParent = 1;
   573    active_flags.sensitiveDataOrigin = 1;
   574    active_flags.userWithAuth = 1;
   575    active_flags.sign = 1;
   576  
   577    if (Tpm2_CreateKey(tpm, parentHandle, parentAuth, authString,
   578                       parent_pcrSelect,
   579                       TPM_ALG_RSA, TPM_ALG_SHA256, active_flags, TPM_ALG_NULL,
   580                       (TPMI_AES_KEY_BITS)0, TPM_ALG_ECB, TPM_ALG_RSASSA,
   581                       1024, 0x010001, &size_public, out_public,
   582                       &size_private, out_private,
   583                       &creation_out, &digest_out, &creation_ticket)) {
   584      printf("Create succeeded private size: %d, public size: %d\n",
   585             size_private, size_public);
   586    } else {
   587      printf("Create failed\n");
   588      return false;
   589    }
   590  
   591    if (Tpm2_Load(tpm, parentHandle, parentAuth, size_public, out_public,
   592                 size_private, out_private, &activeHandle, &pub_name)) {
   593      printf("Load succeeded, handle: %08x\n", activeHandle);
   594    } else {
   595      Tpm2_FlushContext(tpm, ekHandle);
   596      Tpm2_FlushContext(tpm, parentHandle);
   597      printf("Load failed\n");
   598      return false;
   599    }
   600  
   601    TPM2B_DIGEST credential;
   602    TPM2B_ID_OBJECT credentialBlob;
   603    TPM2B_ENCRYPTED_SECRET secret;
   604    TPM2B_DIGEST recovered_credential;
   605  
   606    memset((void*)&credential, 0, sizeof(TPM2B_DIGEST));
   607    memset((void*)&secret, 0, sizeof(TPM2B_ENCRYPTED_SECRET));
   608    memset((void*)&credentialBlob, 0, sizeof(TPM2B_ID_OBJECT));
   609    credential.size = 20;
   610    for (int i = 0; i < 20; i++)
   611      credential.buffer[i] = i + 1;
   612  
   613    TPM2B_PUBLIC active_pub_out;
   614    TPM2B_NAME active_pub_name;
   615    TPM2B_NAME active_qualified_pub_name;
   616    uint16_t active_pub_blob_size = 1024;
   617    byte active_pub_blob[1024];
   618  
   619    memset((void*)&active_pub_out, 0, sizeof(TPM2B_PUBLIC));
   620  
   621    if (Tpm2_ReadPublic(tpm, activeHandle,
   622                        &active_pub_blob_size, active_pub_blob,
   623                        &active_pub_out, &active_pub_name,
   624                        &active_qualified_pub_name)) {
   625      printf("ReadPublic succeeded\n");
   626    } else {
   627      printf("ReadPublic failed\n");
   628      return false;
   629    }
   630    printf("Active Name (%d): ", active_pub_name.size);
   631    PrintBytes(active_pub_name.size, active_pub_name.name);
   632    printf("\n");
   633  
   634    if (Tpm2_MakeCredential(tpm, ekHandle, credential, active_pub_name,
   635                            &credentialBlob, &secret)) {
   636      printf("MakeCredential succeeded\n");
   637    } else {
   638      Tpm2_FlushContext(tpm, parentHandle);
   639      printf("MakeCredential failed\n");
   640      Tpm2_FlushContext(tpm, activeHandle);
   641      Tpm2_FlushContext(tpm, parentHandle);
   642      Tpm2_FlushContext(tpm, ekHandle);
   643      return false;
   644    }
   645    printf("credBlob size: %d\n", credentialBlob.size);
   646    printf("secret size: %d\n", secret.size);
   647    if (Tpm2_ActivateCredential(tpm, activeHandle, ekHandle,
   648                                parentAuth, emptyAuth,
   649                                credentialBlob, secret,
   650                                &recovered_credential)) {
   651      printf("ActivateCredential succeeded\n");
   652      printf("Recovered credential (%d): ", recovered_credential.size);
   653      PrintBytes(recovered_credential.size, recovered_credential.buffer);
   654      printf("\n");
   655    } else {
   656      Tpm2_FlushContext(tpm, parentHandle);
   657      printf("ActivateCredential failed\n");
   658      Tpm2_FlushContext(tpm, activeHandle);
   659      Tpm2_FlushContext(tpm, parentHandle);
   660      Tpm2_FlushContext(tpm, ekHandle);
   661      return false;
   662    }
   663    Tpm2_FlushContext(tpm, activeHandle);
   664    Tpm2_FlushContext(tpm, parentHandle);
   665    Tpm2_FlushContext(tpm, ekHandle);
   666    return true;
   667  }
   668  
   669  bool Tpm2_ContextCombinedTest(LocalTpm& tpm) {
   670    TPM_HANDLE handle;
   671    uint16_t size = 4096;
   672    byte saveArea[4096];
   673    string authString("01020304");
   674  
   675    TPM2B_PUBLIC pub_out;
   676    TPML_PCR_SELECTION pcrSelect;
   677    InitSinglePcrSelection(7, TPM_ALG_SHA1, &pcrSelect);
   678  
   679    TPMA_OBJECT primary_flags;
   680    *(uint32_t*)(&primary_flags) = 0;
   681    primary_flags.fixedTPM = 1;
   682    primary_flags.fixedParent = 1;
   683    primary_flags.sensitiveDataOrigin = 1;
   684    primary_flags.userWithAuth = 1;
   685    primary_flags.sign = 1;
   686  
   687    if (Tpm2_CreatePrimary(tpm, TPM_RH_OWNER, authString, pcrSelect,
   688                           TPM_ALG_RSA, TPM_ALG_SHA1, primary_flags, TPM_ALG_NULL,
   689                           (TPMI_AES_KEY_BITS)0, TPM_ALG_ECB, TPM_ALG_RSASSA,
   690                           1024, 0x010001,
   691                           &handle, &pub_out)) {
   692      printf("CreatePrimary succeeded\n");
   693    } else {
   694      printf("CreatePrimary failed\n");
   695      return false;
   696    }
   697    if (Tpm2_SaveContext(tpm, handle, &size, saveArea)) {
   698      printf("Tpm2_SaveContext succeeds, save area %d\n", size);
   699    } else {
   700      printf("Tpm2_SaveContext failed\n");
   701      return false;
   702    }
   703    if (Tpm2_FlushContext(tpm, handle)) {
   704      printf("Tpm2_FlushContext succeeds, save area %d\n", size);
   705    } else {
   706      printf("Tpm2_FlushContext failed\n");
   707      return false;
   708    }
   709    handle = 0;
   710    if (Tpm2_LoadContext(tpm, size, saveArea, &handle)) {
   711      printf("Tpm2_LoadContext succeeds, handle: %08x, save area %d\n",
   712             handle, size);
   713    } else {
   714      printf("Tpm2_LoadContext failed\n");
   715      return false;
   716    }
   717    Tpm2_FlushContext(tpm, handle);
   718    return true;
   719  }
   720  
   721  bool Tpm2_NvCombinedTest(LocalTpm& tpm) {
   722    int slot = 1000;
   723    string authString("01020304");
   724    uint16_t size_data = 16;
   725    byte data_in[512] = {
   726      0x9, 0x8, 0x7, 0x6,
   727      0x9, 0x8, 0x7, 0x6,
   728      0x9, 0x8, 0x7, 0x6,
   729      0x9, 0x8, 0x7, 0x6
   730    };
   731    uint16_t size_out = 512;
   732    byte data_out[512];
   733    TPM_HANDLE nv_handle = GetNvHandle(slot);
   734  
   735    if (Tpm2_UndefineSpace(tpm, TPM_RH_OWNER, nv_handle)) {
   736      printf("Tpm2_UndefineSpace %d succeeds\n", slot);
   737    } else {
   738      printf("Tpm2_UndefineSpace fails (but that's OK usually)\n");
   739    }
   740    if (Tpm2_DefineSpace(tpm, TPM_RH_OWNER, nv_handle, authString, 0, nullptr,
   741                         NV_AUTHWRITE | NV_AUTHREAD, size_data) ) {
   742      printf("Tpm2_DefineSpace %d succeeds\n", nv_handle);
   743    } else {
   744      printf("Tpm2_DefineSpace fails\n");
   745      return false;
   746    }
   747    if (Tpm2_WriteNv(tpm, nv_handle, authString, size_data, data_in)) {
   748      printf("Tpm2_WriteNv %d succeeds, %d bytes written\n", nv_handle, size_data);
   749    } else {
   750      printf("Tpm2_WriteNv fails\n");
   751      return false;
   752    }
   753    size_out = size_data;
   754    if (Tpm2_ReadNv(tpm, nv_handle, authString, &size_out, data_out)) {
   755      printf("Tpm2_ReadNv %d succeeds: ", nv_handle);
   756      PrintBytes(size_out, data_out);
   757      printf("\n");
   758    } else {
   759      printf("Tpm2_ReadNv fails\n");
   760      return false;
   761    }
   762  
   763    size_data = 8;
   764    memset(data_out, 0, 16);
   765    // Counter tests
   766    printf("\n\nCounter tests\n");
   767    if (Tpm2_UndefineSpace(tpm, TPM_RH_OWNER, nv_handle)) {
   768      printf("Tpm2_UndefineSpace %d succeeds\n", slot);
   769    } else {
   770      printf("Tpm2_UndefineSpace fails (but that's OK usually)\n");
   771    }
   772    // Should be AuthRead, AuthWrite, Counter, Sha256
   773    if (Tpm2_DefineSpace(tpm, TPM_RH_OWNER, nv_handle, authString, 0, nullptr,
   774                         NV_COUNTER | NV_AUTHWRITE | NV_AUTHREAD, 8)) {
   775      printf("Tpm2_DefineSpace %d succeeds\n", nv_handle);
   776    } else {
   777      printf("Tpm2_DefineSpace fails\n");
   778      return false;
   779    }
   780    if (Tpm2_IncrementNv(tpm, nv_handle, authString)) {
   781      printf("Tpm2_IncrementNv succeeds\n");
   782    } else {
   783      printf("Tpm2_IncrementNv fails\n");
   784    }
   785    size_out = size_data;
   786    if (Tpm2_ReadNv(tpm, nv_handle, authString, &size_out, data_out)) {
   787      printf("Tpm2_ReadNv succeeds\n");
   788      printf("Counter value: "); PrintBytes(size_out, data_out); printf("\n");
   789    } else {
   790      printf("Tpm2_ReadNv fails\n");
   791    }
   792    if (Tpm2_IncrementNv(tpm, nv_handle, authString)) {
   793      printf("Tpm2_IncrementNv succeeds\n");
   794    } else {
   795      printf("Tpm2_IncrementNv fails\n");
   796    }
   797    if (Tpm2_ReadNv(tpm, nv_handle, authString, &size_out, data_out)) {
   798      printf("Tpm2_ReadNv succeeds\n");
   799      printf("Counter value: "); PrintBytes(size_out, data_out); printf("\n");
   800    } else {
   801      printf("Tpm2_ReadNv fails\n");
   802    }
   803    if (Tpm2_UndefineSpace(tpm, TPM_RH_OWNER, nv_handle)) {
   804      printf("Tpm2_UndefineSpace %d succeeds\n", slot);
   805    } else {
   806      printf("Tpm2_UndefineSpace fails (but that's OK usually)\n");
   807    }
   808  
   809    return true;
   810  }
   811  
   812  bool Tpm2_KeyCombinedTest(LocalTpm& tpm, int pcr_num) {
   813    string authString("01020304");
   814    string parentAuth("01020304");
   815    string emptyAuth;
   816  
   817    TPM_HANDLE parent_handle;
   818    TPM2B_PUBLIC pub_out;
   819    TPML_PCR_SELECTION pcrSelect;
   820    InitSinglePcrSelection(pcr_num, TPM_ALG_SHA1, &pcrSelect);
   821  
   822    TPMA_OBJECT primary_flags;
   823    *(uint32_t*)(&primary_flags) = 0;
   824    primary_flags.fixedTPM = 1;
   825    primary_flags.fixedParent = 1;
   826    primary_flags.sensitiveDataOrigin = 1;
   827    primary_flags.userWithAuth = 1;
   828    primary_flags.decrypt = 1;
   829    primary_flags.restricted = 1;
   830  
   831    if (Tpm2_CreatePrimary(tpm, TPM_RH_OWNER, authString, pcrSelect,
   832                           TPM_ALG_RSA, TPM_ALG_SHA1, primary_flags,
   833                           TPM_ALG_AES, 128, TPM_ALG_CFB, TPM_ALG_NULL,
   834                           1024, 0x010001,
   835                           &parent_handle, &pub_out)) {
   836      printf("CreatePrimary succeeded\n");
   837    } else {
   838      printf("CreatePrimary failed\n");
   839      return false;
   840    }
   841    TPM2B_CREATION_DATA creation_out;
   842    TPM2B_DIGEST digest_out;
   843    TPMT_TK_CREATION creation_ticket;
   844    int size_public = MAX_SIZE_PARAMS;
   845    byte out_public[MAX_SIZE_PARAMS];
   846    int size_private = MAX_SIZE_PARAMS;
   847    byte out_private[MAX_SIZE_PARAMS];
   848  
   849    TPMA_OBJECT create_flags;
   850    *(uint32_t*)(&create_flags) = 0;
   851    create_flags.fixedTPM = 1;
   852    create_flags.fixedParent = 1;
   853    create_flags.sensitiveDataOrigin = 1;
   854    create_flags.userWithAuth = 1;
   855    create_flags.sign = 1;
   856  
   857    if (Tpm2_CreateKey(tpm, parent_handle, parentAuth, authString, pcrSelect,
   858                       TPM_ALG_RSA, TPM_ALG_SHA1, create_flags, TPM_ALG_NULL,
   859                       (TPMI_AES_KEY_BITS)0, TPM_ALG_ECB, TPM_ALG_RSASSA,
   860                       1024, 0x010001, &size_public, out_public,
   861                       &size_private, out_private,
   862                       &creation_out, &digest_out, &creation_ticket)) {
   863      printf("Create succeeded private size: %d, public size: %d\n",
   864             size_private, size_public);
   865    } else {
   866      printf("Create failed\n");
   867      return false;
   868    }
   869  
   870    TPM_HANDLE load_handle = 0;
   871    TPM2B_NAME name;
   872    if (Tpm2_Load(tpm, parent_handle, parentAuth, size_public, out_public,
   873                 size_private, out_private, &load_handle, &name)) {
   874      printf("Load succeeded, handle: %08x\n", load_handle);
   875    } else {
   876      Tpm2_FlushContext(tpm, parent_handle);
   877      printf("Load failed\n");
   878      return false;
   879    }
   880    TPM2B_DATA qualifyingData;
   881    TPM2B_ATTEST attest;
   882    TPMT_SIGNATURE sig;
   883    qualifyingData.size = 3;
   884    qualifyingData.buffer[0] = 5;
   885    qualifyingData.buffer[1] = 6;
   886    qualifyingData.buffer[2] = 7;
   887    if (Tpm2_Certify(tpm, load_handle, load_handle,
   888                    parentAuth, parentAuth,
   889                    qualifyingData, &attest, &sig)) {
   890      printf("Certify succeeded\n");
   891      printf("attested (%d): ", attest.size);
   892      PrintBytes(attest.size, attest.attestationData);
   893      printf("\n");
   894      printf("signature (%d %d %d): ", sig.sigAlg, sig.signature.rsassa.hash,
   895             sig.signature.rsassa.sig.size);
   896      PrintBytes(sig.signature.rsassa.sig.size, sig.signature.rsassa.sig.buffer);
   897      printf("\n");
   898    } else {
   899      Tpm2_FlushContext(tpm, load_handle);
   900      Tpm2_FlushContext(tpm, parent_handle);
   901      printf("Certify failed\n");
   902      return false;
   903    }
   904  
   905    // evict Control
   906    TPM_HANDLE persistant_handle = 0x810003e8;
   907  
   908    if (!Tpm2_EvictControl(tpm, TPM_RH_OWNER, persistant_handle,
   909                           authString, persistant_handle)) {
   910    printf("Tpm2_EvictControl first evicting fails\n");
   911    } else {
   912      printf("Tpm2_EvictControl first evicting succeeds\n");
   913    }
   914  
   915    // make control permanent
   916    if (!Tpm2_EvictControl(tpm, TPM_RH_OWNER, load_handle, authString,
   917                         persistant_handle)) {
   918      printf("Tpm2_EvictControl fails\n");
   919    } else {
   920      printf("Tpm2_EvictControl succeeds %08x\n", persistant_handle);
   921    }
   922  
   923    // evict it again
   924    if (!Tpm2_EvictControl(tpm, TPM_RH_OWNER, persistant_handle,
   925                           authString, persistant_handle)) {
   926    printf("Tpm2_EvictControl second evicting fails\n");
   927    } else {
   928      printf("Tpm2_EvictControl second evicting succeeds\n");
   929    }
   930  
   931    if (load_handle != 0)
   932      Tpm2_FlushContext(tpm, load_handle);
   933    Tpm2_FlushContext(tpm, parent_handle);
   934    return true;
   935  }
   936  
   937  
   938  bool Tpm2_SealCombinedTest(LocalTpm& tpm, int pcr_num) {
   939    string authString("01020304");
   940    string parentAuth("01020304");
   941    string emptyAuth;
   942  
   943    TPM_HANDLE parent_handle;
   944    TPM2B_PUBLIC pub_out;
   945    TPML_PCR_SELECTION pcrSelect;
   946    InitSinglePcrSelection(pcr_num, TPM_ALG_SHA1, &pcrSelect);
   947  
   948    TPMA_OBJECT primary_flags;
   949    *(uint32_t*)(&primary_flags) = 0;
   950    primary_flags.fixedTPM = 1;
   951    primary_flags.fixedParent = 1;
   952    primary_flags.sensitiveDataOrigin = 1;
   953    primary_flags.userWithAuth = 1;
   954    primary_flags.decrypt = 1;
   955    primary_flags.restricted = 1;
   956  
   957    if (Tpm2_CreatePrimary(tpm, TPM_RH_OWNER, authString, pcrSelect, 
   958                           TPM_ALG_RSA, TPM_ALG_SHA1, primary_flags,
   959                           TPM_ALG_AES, 128, TPM_ALG_CFB, TPM_ALG_NULL,
   960                           1024, 0x010001,
   961                          &parent_handle, &pub_out)) {
   962      printf("CreatePrimary succeeded\n");
   963    } else {
   964      printf("CreatePrimary failed\n");
   965      return false;
   966    }
   967    TPM2B_DIGEST secret;
   968    secret.size = 16;
   969    for  (int i = 0; i < 16; i++)
   970      secret.buffer[i] = (byte)(i + 1);
   971  
   972    TPM2B_CREATION_DATA creation_out;
   973    TPMT_TK_CREATION creation_ticket;
   974    int size_public = MAX_SIZE_PARAMS;
   975    byte out_public[MAX_SIZE_PARAMS];
   976    int size_private = MAX_SIZE_PARAMS;
   977    byte out_private[MAX_SIZE_PARAMS];
   978  
   979    TPM2B_DIGEST digest_out;
   980    TPM2B_NONCE initial_nonce;
   981    TPM2B_ENCRYPTED_SECRET salt;
   982    TPMT_SYM_DEF symmetric;
   983    TPM_HANDLE session_handle;
   984    TPM2B_NONCE nonce_obj;
   985  
   986    initial_nonce.size = 16;
   987    memset(initial_nonce.buffer, 0, 16);
   988    salt.size = 0;
   989    symmetric.algorithm = TPM_ALG_NULL;
   990    
   991    // Start auth session
   992    if (Tpm2_StartAuthSession(tpm, TPM_RH_NULL, TPM_RH_NULL,
   993                              initial_nonce, salt, TPM_SE_POLICY,
   994                              symmetric, TPM_ALG_SHA1, &session_handle,
   995                              &nonce_obj)) {
   996      printf("Tpm2_StartAuthSession succeeds handle: %08x\n",
   997             session_handle);
   998      printf("nonce (%d): ", nonce_obj.size);
   999      PrintBytes(nonce_obj.size, nonce_obj.buffer);
  1000      printf("\n");
  1001    } else {
  1002      printf("Tpm2_StartAuthSession fails\n");
  1003      return false;
  1004    }
  1005  
  1006    TPM2B_DIGEST policy_digest;
  1007    // get policy digest
  1008    if(Tpm2_PolicyGetDigest(tpm, session_handle, &policy_digest)) {
  1009      printf("PolicyGetDigest before Pcr succeeded: ");
  1010      PrintBytes(policy_digest.size, policy_digest.buffer); printf("\n");
  1011    } else {
  1012      Tpm2_FlushContext(tpm, session_handle);
  1013      printf("PolicyGetDigest failed\n");
  1014      return false;
  1015    }
  1016  
  1017    if (Tpm2_PolicyPassword(tpm, session_handle)) {
  1018      printf("PolicyPassword succeeded\n");
  1019    } else {
  1020      Tpm2_FlushContext(tpm, session_handle);
  1021      printf("PolicyPassword failed\n");
  1022      return false;
  1023    }
  1024  
  1025    TPM2B_DIGEST expected_digest;
  1026    expected_digest.size = 0;
  1027    if (Tpm2_PolicyPcr(tpm, session_handle,
  1028                       expected_digest, pcrSelect)) {
  1029      printf("PolicyPcr succeeded\n");
  1030    } else {
  1031      printf("PolicyPcr failed\n");
  1032      Tpm2_FlushContext(tpm, session_handle);
  1033      return false;
  1034    }
  1035  
  1036    if(Tpm2_PolicyGetDigest(tpm, session_handle, &policy_digest)) {
  1037      printf("PolicyGetDigest succeeded: ");
  1038      PrintBytes(policy_digest.size, policy_digest.buffer); printf("\n");
  1039    } else {
  1040      printf("PolicyGetDigest failed\n");
  1041      return false;
  1042    }
  1043  
  1044    TPMA_OBJECT create_flags;
  1045    *(uint32_t*)(&create_flags) = 0;
  1046    create_flags.fixedTPM = 1;
  1047    create_flags.fixedParent = 1;
  1048  
  1049    if (Tpm2_CreateSealed(tpm, parent_handle, policy_digest.size,
  1050                          policy_digest.buffer, parentAuth, secret.size,
  1051                          secret.buffer, pcrSelect, TPM_ALG_SHA1, create_flags,
  1052                          TPM_ALG_NULL, (TPMI_AES_KEY_BITS)0, TPM_ALG_ECB,
  1053                          TPM_ALG_RSASSA, 1024, 0x010001,
  1054                          &size_public, out_public, &size_private, out_private,
  1055                          &creation_out, &digest_out, &creation_ticket)) {
  1056      printf("Create with digest succeeded private size: %d, public size: %d\n",
  1057             size_private, size_public);
  1058    } else {
  1059      printf("Create with digest failed\n");
  1060      Tpm2_FlushContext(tpm, session_handle);
  1061      return false;
  1062    }
  1063  
  1064    TPM_HANDLE load_handle;
  1065    TPM2B_NAME name;
  1066    if (Tpm2_Load(tpm, parent_handle, parentAuth, size_public, out_public,
  1067                 size_private, out_private, &load_handle, &name)) {
  1068      printf("Load succeeded\n");
  1069    } else {
  1070      printf("Load failed\n");
  1071      Tpm2_FlushContext(tpm, session_handle);
  1072      return false;
  1073    }
  1074  
  1075    int unsealed_size = MAX_SIZE_PARAMS;
  1076    byte unsealed[MAX_SIZE_PARAMS];
  1077    TPM2B_DIGEST hmac;
  1078    hmac.size = 0;
  1079    if (!Tpm2_Unseal(tpm, load_handle, parentAuth, session_handle,
  1080                     nonce_obj, 0x01, hmac,
  1081                     &unsealed_size, unsealed)) {
  1082      printf("Unseal failed\n");
  1083      Tpm2_FlushContext(tpm, session_handle);
  1084      Tpm2_FlushContext(tpm, load_handle);
  1085      return false;
  1086    }
  1087    printf("Unseal succeeded, unsealed (%d): ", unsealed_size); 
  1088    PrintBytes(unsealed_size, unsealed);
  1089    printf("\n"); 
  1090    Tpm2_FlushContext(tpm, session_handle);
  1091    Tpm2_FlushContext(tpm, load_handle);
  1092    return true;
  1093  }
  1094  
  1095  bool Tpm2_QuoteCombinedTest(LocalTpm& tpm, int pcr_num) {
  1096    string authString("01020304");
  1097    string parentAuth("01020304");
  1098    string emptyAuth;
  1099  
  1100    TPM_HANDLE parent_handle;
  1101    TPM2B_PUBLIC pub_out;
  1102    TPML_PCR_SELECTION pcr_selection;
  1103    InitSinglePcrSelection(pcr_num, TPM_ALG_SHA1, &pcr_selection);
  1104  
  1105    TPMA_OBJECT primary_flags;
  1106    *(uint32_t*)(&primary_flags) = 0;
  1107    primary_flags.fixedTPM = 1;
  1108    primary_flags.fixedParent = 1;
  1109    primary_flags.sensitiveDataOrigin = 1;
  1110    primary_flags.userWithAuth = 1;
  1111    primary_flags.decrypt = 1;
  1112    primary_flags.restricted = 1;
  1113  
  1114    if (Tpm2_CreatePrimary(tpm, TPM_RH_OWNER, authString, pcr_selection, 
  1115                           TPM_ALG_RSA, TPM_ALG_SHA1, primary_flags,
  1116                           TPM_ALG_AES, 128, TPM_ALG_CFB, TPM_ALG_NULL,
  1117                           1024, 0x010001,
  1118                           &parent_handle, &pub_out)) {
  1119      printf("CreatePrimary succeeded\n");
  1120    } else {
  1121      printf("CreatePrimary failed\n");
  1122      return false;
  1123    }
  1124  
  1125    if (pcr_num >= 0) {
  1126      uint16_t size_eventData = 3;
  1127      byte eventData[3] = {1, 2, 3};
  1128      if (Tpm2_PCR_Event(tpm, pcr_num, size_eventData, eventData)) {
  1129        printf("Tpm2_PCR_Event succeeded\n");
  1130      } else {
  1131        printf("Tpm2_PCR_Event failed\n");
  1132      }
  1133    }
  1134  
  1135    TPM2B_CREATION_DATA creation_out;
  1136    TPMT_TK_CREATION creation_ticket;
  1137    int size_public = MAX_SIZE_PARAMS;
  1138    byte out_public[MAX_SIZE_PARAMS];
  1139    int size_private = MAX_SIZE_PARAMS;
  1140    byte out_private[MAX_SIZE_PARAMS];
  1141    TPM2B_DIGEST digest_out;
  1142  
  1143    TPMA_OBJECT create_flags;
  1144    *(uint32_t*)(&create_flags) = 0;
  1145    create_flags.fixedTPM = 1;
  1146    create_flags.fixedParent = 1;
  1147    create_flags.sensitiveDataOrigin = 1;
  1148    create_flags.userWithAuth = 1;
  1149    create_flags.sign = 1;
  1150    create_flags.restricted = 1;
  1151  
  1152    if (Tpm2_CreateKey(tpm, parent_handle, parentAuth, authString, pcr_selection,
  1153                       TPM_ALG_RSA, TPM_ALG_SHA1, create_flags, TPM_ALG_NULL,
  1154                       (TPMI_AES_KEY_BITS)0, TPM_ALG_ECB, TPM_ALG_RSASSA,
  1155                       1024, 0x010001,
  1156                       &size_public, out_public, &size_private, out_private,
  1157                       &creation_out, &digest_out, &creation_ticket)) {
  1158      printf("Create succeeded, private size: %d, public size: %d\n",
  1159             size_private, size_public);
  1160    } else {
  1161      printf("Create failed\n");
  1162      return false;
  1163    }
  1164  
  1165    TPM_HANDLE load_handle;
  1166    TPM2B_NAME name;
  1167    if (Tpm2_Load(tpm, parent_handle, parentAuth, size_public, out_public,
  1168                 size_private, out_private, &load_handle, &name)) {
  1169      printf("Load succeeded\n");
  1170    } else {
  1171      printf("Load failed\n");
  1172      return false;
  1173    }
  1174  
  1175    TPM2B_DATA to_quote;
  1176    to_quote.size = 16;
  1177    for  (int i = 0; i < 16; i++)
  1178      to_quote.buffer[i] = (byte)(i + 1);
  1179    TPMT_SIG_SCHEME scheme;
  1180  
  1181    int quote_size = MAX_SIZE_PARAMS;
  1182    byte quoted[MAX_SIZE_PARAMS];
  1183    int sig_size = MAX_SIZE_PARAMS;
  1184    byte sig[MAX_SIZE_PARAMS];
  1185    if (!Tpm2_Quote(tpm, load_handle, parentAuth,
  1186                    to_quote.size, to_quote.buffer,
  1187                    scheme, pcr_selection, TPM_ALG_RSA, TPM_ALG_SHA1,
  1188                    &quote_size, quoted, &sig_size, sig)) {
  1189      printf("Quote failed\n");
  1190      Tpm2_FlushContext(tpm, load_handle);
  1191      Tpm2_FlushContext(tpm, parent_handle);
  1192      return false;
  1193    }
  1194    printf("Quote succeeded, quoted (%d): ", quote_size); 
  1195    PrintBytes(quote_size, quoted);
  1196    printf("\n"); 
  1197    printf("Sig (%d): ", sig_size); 
  1198    PrintBytes(sig_size, sig);
  1199    printf("\n"); 
  1200    Tpm2_FlushContext(tpm, load_handle);
  1201    Tpm2_FlushContext(tpm, parent_handle);
  1202    return true;
  1203  }
  1204  
  1205  
  1206  void seperate_key_test() {
  1207    RSA* rsa_key = RSA_generate_key(2048, 0x010001ULL, nullptr, nullptr);
  1208    if (rsa_key == nullptr) {
  1209      printf("Can't generate RSA key\n");
  1210      return;
  1211    }
  1212    TPM2B_DIGEST secret;
  1213    TPM2B_ENCRYPTED_SECRET salt;
  1214    secret.size = 20;
  1215    memcpy(secret.buffer, (byte*)"12345678901234567890", secret.size);
  1216  
  1217  // Encrypt salt
  1218    printf("\nencrypting salt\n");
  1219    int size_padded_secret= 256;
  1220    byte padded_secret[256];
  1221    RSA_padding_add_PKCS1_OAEP(padded_secret, 256, secret.buffer, secret.size,
  1222        (byte*)"SECRET", strlen("SECRET")+1);
  1223    int n = RSA_public_encrypt(size_padded_secret, padded_secret, salt.secret,
  1224                               rsa_key, RSA_NO_PADDING);
  1225    salt.size = n;
  1226  
  1227    byte decrypted_with_pad[512];
  1228    byte recovered_secret[512];
  1229    memset(recovered_secret, 0, 512);
  1230    memset(decrypted_with_pad, 0, 512);
  1231  
  1232    printf("\nEncrypted salt (%d): ", n);
  1233    PrintBytes(n, salt.secret); printf("\n");
  1234    int m = RSA_private_decrypt(n, (byte*) salt.secret,
  1235                 (byte*)decrypted_with_pad, rsa_key,
  1236                 RSA_NO_PADDING);
  1237    if (m < 0) {
  1238      printf("Can't decrypt\n");
  1239      return;
  1240    }
  1241    printf("decrypted(%d): ", m);
  1242    PrintBytes(m, decrypted_with_pad);printf("\n");
  1243    salt.size = m;
  1244    int k = 0;
  1245    while(k < 256 && decrypted_with_pad[k] == 0) k++;
  1246    RSA_padding_check_PKCS1_OAEP(recovered_secret, 256, 
  1247        &decrypted_with_pad[k], 256-k, 256,
  1248        (byte*)"SECRET", strlen("SECRET")+1);
  1249  }
  1250  
  1251  // For Jethro
  1252  bool Tpm2_NvCombinedSessionTest(LocalTpm& tpm) {
  1253    printf("Tpm2_NvCombinedSessionTest\n\n");
  1254    extern int CreatePasswordAuthArea(string& password, int size, byte* buf);
  1255  
  1256    int slot = 1000;
  1257    string authString("01020304");
  1258    uint16_t size_data = 8;
  1259    uint16_t size_out = 512;
  1260    byte data_out[512];
  1261    TPM_HANDLE nv_handle = GetNvHandle(slot);
  1262    bool ret = true;
  1263  
  1264    TPM2B_ENCRYPTED_SECRET salt;
  1265    TPM_HANDLE sessionHandle = 0;
  1266    TPML_PCR_SELECTION pcrSelect;
  1267    memset((void*)&pcrSelect, 0, sizeof(TPML_PCR_SELECTION));
  1268  
  1269    TPM2B_DIGEST secret;
  1270    ProtectedSessionAuthInfo authInfo;
  1271    TPMT_SYM_DEF symmetric;
  1272  
  1273    authInfo.hash_alg_ = TPM_ALG_SHA1;
  1274    int hashSize = SizeHash(authInfo.hash_alg_);
  1275  
  1276    // If encryption.
  1277    symmetric.algorithm = TPM_ALG_AES;
  1278    symmetric.keyBits.aes = 128;
  1279    symmetric.mode.aes = TPM_ALG_CFB;
  1280  
  1281    authInfo.targetAuthValue_.size = authString.size();
  1282    memset(authInfo.targetAuthValue_.buffer, 0, authString.size());
  1283  
  1284    authInfo.newNonce_.size = hashSize;
  1285    authInfo.oldNonce_.size = hashSize;
  1286    memset(authInfo.newNonce_.buffer, 0, hashSize);
  1287    memset(authInfo.oldNonce_.buffer, 0, hashSize);
  1288    RAND_bytes(authInfo.oldNonce_.buffer, authInfo.oldNonce_.size);
  1289  
  1290    memset(secret.buffer, 0, 32);
  1291    secret.size = 20;
  1292    RAND_bytes(secret.buffer, secret.size);
  1293  
  1294  #if 1
  1295    printf("newNonce: ");
  1296    PrintBytes(authInfo.newNonce_.size, authInfo.newNonce_.buffer); printf("\n");
  1297    printf("oldNonce: ");
  1298    PrintBytes(authInfo.oldNonce_.size, authInfo.oldNonce_.buffer); printf("\n");
  1299    printf("Secret:   "); PrintBytes(secret.size, secret.buffer); printf("\n");
  1300  #endif
  1301  
  1302    // Get endorsement key handle
  1303    string emptyAuth;
  1304    TPM_HANDLE ekHandle;
  1305    TPM2B_PUBLIC pub_out;
  1306  
  1307    // TPM_RH_ENDORSEMENT
  1308    TPMA_OBJECT primary_flags;
  1309    *(uint32_t*)(&primary_flags) = 0;
  1310    primary_flags.fixedTPM = 1;
  1311    primary_flags.fixedParent = 1;
  1312    primary_flags.sensitiveDataOrigin = 1;
  1313    primary_flags.userWithAuth = 1;
  1314    primary_flags.decrypt = 1;
  1315    primary_flags.restricted = 1;
  1316  
  1317    // Get rid of the old counter.
  1318    if (Tpm2_UndefineSpace(tpm, TPM_RH_OWNER, nv_handle)) {
  1319      printf("Tpm2_UndefineSpace %d succeeds\n", slot);
  1320    } else {
  1321      printf("Tpm2_UndefineSpace fails (but that's OK usually)\n");
  1322    }
  1323    if (Tpm2_DefineSpace(tpm, TPM_RH_OWNER, nv_handle, authString,
  1324                          0, nullptr, NV_COUNTER | NV_AUTHWRITE | NV_AUTHREAD,
  1325                          size_data)) {
  1326       printf("DefineSpace succeeded\n");
  1327     } else {
  1328       printf("DefineSpace failed\n");
  1329       return false;
  1330     }
  1331    if (Tpm2_IncrementNv(tpm, nv_handle, authString)) {
  1332      printf("Initial Tpm2_IncrementNv succeeds\n");
  1333    } else {
  1334      printf("Initial Tpm2_IncrementNv fails\n");
  1335       return false;
  1336    }
  1337  
  1338    // Get endorsement key.
  1339    if (Tpm2_CreatePrimary(tpm, TPM_RH_ENDORSEMENT, emptyAuth, pcrSelect,
  1340                           TPM_ALG_RSA, TPM_ALG_SHA1, primary_flags,
  1341                           TPM_ALG_AES, 128, TPM_ALG_CFB, TPM_ALG_NULL,
  1342                           2048, 0x010001, &ekHandle, &pub_out)) {
  1343      printf("CreatePrimary succeeded: %08x\n", ekHandle);
  1344    } else {
  1345      printf("CreatePrimary failed\n");
  1346      return false;
  1347    }
  1348  
  1349    TPM2B_NAME pub_name;
  1350    TPM2B_NAME qualified_pub_name;
  1351    uint16_t pub_blob_size = 2048;
  1352    byte pub_blob[2048];
  1353  
  1354    if (Tpm2_ReadPublic(tpm, ekHandle, &pub_blob_size, pub_blob, &pub_out,
  1355                        &pub_name, &qualified_pub_name)) {
  1356      printf("ReadPublic succeeded\n");
  1357    } else {
  1358      printf("ReadPublic failed\n");
  1359      return false;
  1360    }
  1361  
  1362    // Normally, the caller would get the key from the endorsement certificate
  1363    EVP_PKEY* tpmKey = EVP_PKEY_new();
  1364    RSA* rsa_tpmKey = RSA_new();
  1365    rsa_tpmKey->n = bin_to_BN((int)pub_out.publicArea.unique.rsa.size,
  1366                              pub_out.publicArea.unique.rsa.buffer);
  1367    uint64_t exp = 0x010001ULL;
  1368    byte b_exp[16];
  1369    ChangeEndian64((uint64_t*)&exp, (uint64_t*)b_exp);
  1370    rsa_tpmKey->e = bin_to_BN(sizeof(uint64_t), b_exp);
  1371    EVP_PKEY_assign_RSA(tpmKey, rsa_tpmKey);
  1372  
  1373    // Encrypt salt
  1374    byte padded_secret[1024];
  1375    memset(padded_secret, 0, 1024);
  1376    RSA_padding_add_PKCS1_OAEP(padded_secret, 256,
  1377        secret.buffer, secret.size,
  1378        (byte*)"SECRET", strlen("SECRET")+1);
  1379    int n = RSA_public_encrypt(256, padded_secret, salt.secret,
  1380                               rsa_tpmKey, RSA_NO_PADDING);
  1381    salt.size = n;
  1382  
  1383  #if 1
  1384    printf("\nEncrypted salt (%d): ", n);
  1385    PrintBytes(n, salt.secret); printf("\n");
  1386  #endif
  1387  
  1388    authInfo.protectedHandle_ = nv_handle;
  1389    authInfo.protectedAttributes_ = NV_COUNTER | NV_AUTHWRITE | NV_AUTHREAD;
  1390    authInfo.protectedSize_ = size_data;
  1391    authInfo.hash_alg_ = TPM_ALG_SHA1;
  1392    authInfo.tpmSessionAttributes_ = CONTINUESESSION;
  1393    extern int SetPasswordData(string& password, int size, byte* buf);
  1394    byte tbuf[128];
  1395    int l = SetPasswordData(authString, 128, tbuf);
  1396    authInfo.targetAuthValue_.size = l - 2;
  1397    memcpy(authInfo.targetAuthValue_.buffer, &tbuf[2], l - 2);
  1398    
  1399    // Start auth session.
  1400      if (Tpm2_StartProtectedAuthSession(tpm, ekHandle, TPM_RH_NULL, authInfo,
  1401           salt, TPM_SE_HMAC, symmetric, authInfo.hash_alg_, &sessionHandle)) {
  1402      printf("Tpm2_StartProtectedAuthSession succeeds handle: %08x\n",
  1403             sessionHandle);
  1404    } else {
  1405      printf("Tpm2_StartProtectedAuthSession fails\n");
  1406      ret = false;
  1407      goto done;
  1408    }
  1409    authInfo.sessionHandle_ = sessionHandle;
  1410  
  1411  #if 1
  1412    printf("\nAfterStartProtectedAuthSession\n");
  1413    printf("newNonce: ");
  1414    PrintBytes(authInfo.newNonce_.size, authInfo.newNonce_.buffer); printf("\n");
  1415    printf("oldNonce: ");
  1416    PrintBytes(authInfo.oldNonce_.size, authInfo.oldNonce_.buffer); printf("\n");
  1417  #endif
  1418  
  1419    // Calculate session key.
  1420    if (!CalculateSessionKey(authInfo, secret)) {
  1421      printf("Can't calculate HMac session key\n");
  1422      ret = false;
  1423      goto done;
  1424    }
  1425  
  1426  #if 1
  1427    printf("After CalculateSessionKey before IncrementProtected\n");
  1428    printf("newNonce: ");
  1429    PrintBytes(authInfo.newNonce_.size, authInfo.newNonce_.buffer); printf("\n");
  1430    printf("oldNonce: ");
  1431    PrintBytes(authInfo.oldNonce_.size, authInfo.oldNonce_.buffer); printf("\n");
  1432  #endif
  1433  
  1434    if (Tpm2_IncrementProtectedNv(tpm, nv_handle, authInfo)) {
  1435      printf("Tpm2_IncrementProtectedNv %d succeeds\n", nv_handle);
  1436    } else {
  1437      printf("Tpm2_IncrementProtectedNv fails\n");
  1438      ret = false;
  1439      goto done;
  1440    }
  1441  
  1442  #if 1
  1443    printf("Read Protected\n");
  1444  #endif
  1445  
  1446    size_out = 8;
  1447    if (Tpm2_ReadProtectedNv(tpm, nv_handle, authInfo, &size_out, data_out)) {
  1448      printf("Tpm2_ReadProtectedNv %d succeeds: ", nv_handle);
  1449      PrintBytes(size_out, data_out);
  1450      printf("\n");
  1451    } else {
  1452      printf("Tpm2_ReadProtectedNv fails\n");
  1453      ret = false;
  1454      goto done;
  1455    }
  1456  
  1457  done:
  1458    if (sessionHandle != 0) {
  1459      Tpm2_FlushContext(tpm, sessionHandle);
  1460    }
  1461    if (ekHandle != 0) {
  1462      Tpm2_FlushContext(tpm, ekHandle);
  1463    }
  1464    return ret;
  1465  }