github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/src/tpm2/CreateAndSaveCloudProxyKeyHierarchy.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  //
    14  // Copyright 2015 Google Corporation, All Rights Reserved.
    15  //
    16  // Licensed under the Apache License, Version 2.0 (the "License");
    17  // you may not use this file except in compliance with the License.
    18  // You may obtain a copy of the License at
    19  //     http://www.apache.org/licenses/LICENSE-2.0
    20  // or in the the file LICENSE-2.0.txt in the top level sourcedirectory
    21  // Unless required by applicable law or agreed to in writing, software
    22  // distributed under the License is distributed on an "AS IS" BASIS,
    23  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    24  // See the License for the specific language governing permissions and
    25  // limitations under the License
    26  //
    27  // Portions of this code were derived TPM2.0-TSS published
    28  // by Intel under the license set forth in intel_license.txt
    29  // and downloaded on or about August 6, 2015.
    30  // Portions of this code were derived tboot published
    31  // by Intel under the license set forth in intel_license.txt
    32  // and downloaded on or about August 6, 2015.
    33  // Portions of this code were derived from the crypto utility
    34  // published by John Manferdelli under the Apache 2.0 license.
    35  // See github.com/jlmucb/crypto.
    36  // File: CreateAndSaveCloudProxyKeyHierarchy.cc
    37  
    38  
    39  // This program creates a primary key, signing key (for quotes) and
    40  // sealing key under the owner hierarchy and saves them to the 
    41  //  cloudproxy defined namespace in nv ram so they can be reloaded.
    42  // NV ram is protected with PCR's of current "authenticated boot" so
    43  // they can only be reread by the same cloudproxy environment.
    44  // It optionally seals an input string and quotes a quote string.
    45  // This program removes existing cloudproxy slots with same names
    46  // and slot numbers.
    47  
    48  
    49  // Calling sequence
    50  //   CreateAndSaveCloudProxyKeyHierarchy.exe --cloudproxy_namespace="name"
    51  //      --slot_primary=int32 --slot_seal=int32 --slot_quote=int32
    52  //      --seal_value=value-string --quote_value=value-string
    53  //      --pcr_hash_alg_name=[sha1 | sha256]
    54  //      --pcr_list="int, int, ..." --seal_output_file=output-file-name
    55  //      --quote_output_file= output-file-name --pcr_file=output-file-name
    56  
    57  using std::string;
    58  
    59  
    60  #define CALLING_SEQUENCE "CreateAndSaveCloudProxyKeyHierarchy.exe " \
    61  "--slot_primary=int32 --slot_seal=int32 " \
    62  "--slot_quote=int32 " \
    63  "--seal_value=value-string --quote_value=value-string " \
    64  "--pcr_hash_alg_name=[sha1 | sha256] " \
    65  "--pcr_list='int, int, ...' --seal_output_file=output-file-name " \
    66  "--quote_output_file= output-file-name --pcr_file=output-file-name\n"
    67  
    68  void PrintOptions() {
    69    printf("Calling sequence: %s", CALLING_SEQUENCE);
    70  }
    71  
    72  DEFINE_int32(slot_primary, 1, "");
    73  DEFINE_int32(slot_seal, 2, "");
    74  DEFINE_int32(slot_quote, 3, "");
    75  DEFINE_string(seal_value, "", "test seal value");
    76  DEFINE_string(quote_value, "", "test quote value");
    77  DEFINE_string(pcr_hash_alg_name, "", "hash alg (sha1 or sha256");
    78  DEFINE_string(hash_alg, "sha1", "hash alg (sha1 or sha256");
    79  DEFINE_string(pcr_list, "", "comma separated pcr list");
    80  DEFINE_string(seal_output_file, "", "output-file-name");
    81  DEFINE_string(quote_output_file, "", "output-file-name");
    82  DEFINE_string(pcr_file, "", "output-file-name");
    83  
    84  #ifndef GFLAGS_NS
    85  #define GFLAGS_NS google
    86  #endif
    87  
    88  #define MAX_SIZE_PARAMS 8192
    89  #define DEBUG
    90  
    91  int main(int an, char** av) {
    92    LocalTpm tpm;
    93    int ret_val = 0;
    94  
    95    printf("\nCreateAndSaveCloudProxyKeyHierarchy\n\n");
    96  
    97    GFLAGS_NS::ParseCommandLineFlags(&an, &av, true);
    98    if (!tpm.OpenTpm("/dev/tpm0")) {
    99      printf("Can't open tpm\n");
   100      return 1;
   101    }
   102  
   103    // OpenSSL_add_all_algorithms();
   104    // ERR_load_crypto_strings();
   105  
   106    // Create the Heirarchy 
   107    string authString("01020304");
   108    string parentAuth("01020304");
   109    string emptyAuth;
   110    
   111    TPML_PCR_SELECTION pcrSelect;
   112    TPMA_OBJECT root_flags;
   113  
   114    TPM2B_CREATION_DATA creation_out;
   115    TPM2B_DIGEST digest_out;
   116    TPMT_TK_CREATION creation_ticket;
   117  
   118    TPM_HANDLE root_handle = 0; 
   119    TPM2B_PUBLIC root_pub_out;
   120  
   121    TPM_HANDLE seal_load_handle = 0;
   122    TPMA_OBJECT seal_create_flags;
   123    TPM2B_NAME seal_name;
   124    int seal_size_public = MAX_SIZE_PARAMS;
   125    byte seal_out_public[MAX_SIZE_PARAMS];
   126    int seal_size_private = MAX_SIZE_PARAMS;
   127    byte seal_out_private[MAX_SIZE_PARAMS];
   128  
   129    TPMA_OBJECT quote_create_flags;
   130    TPM2B_NAME quote_name;
   131    TPM_HANDLE quote_load_handle = 0;
   132    int quote_size_public = MAX_SIZE_PARAMS;
   133    byte quote_out_public[MAX_SIZE_PARAMS];
   134    int quote_size_private = MAX_SIZE_PARAMS;
   135    byte quote_out_private[MAX_SIZE_PARAMS];
   136  
   137    TPM_HANDLE nv_handle = 0;
   138    byte context_save_area[MAX_SIZE_PARAMS];
   139    uint16_t context_data_size = MAX_SIZE_PARAMS;
   140  
   141    TPM_HANDLE sealed_load_handle = 0;
   142  
   143    TPM_ALG_ID hash_alg_id;
   144    if (FLAGS_hash_alg == "sha1") {
   145      hash_alg_id = TPM_ALG_SHA1;
   146    } else if (FLAGS_hash_alg == "sha256") {
   147      hash_alg_id = TPM_ALG_SHA256;
   148    } else {
   149      printf("Unknown hash algorithm\n");
   150      return 1;
   151    }
   152  
   153    InitSinglePcrSelection(7, hash_alg_id, &pcrSelect);
   154  
   155    // root of hierarchy 
   156    *(uint32_t*)(&root_flags) = 0;
   157    root_flags.fixedTPM = 1;
   158    root_flags.fixedParent = 1;
   159    root_flags.sensitiveDataOrigin = 1;
   160    root_flags.userWithAuth = 1;
   161    root_flags.decrypt = 1;
   162    root_flags.restricted = 1;
   163    if (Tpm2_CreatePrimary(tpm, TPM_RH_OWNER, authString, pcrSelect,
   164                           TPM_ALG_RSA, hash_alg_id, root_flags,
   165                           TPM_ALG_AES, 128, TPM_ALG_CFB, TPM_ALG_NULL,
   166                           2048, 0x010001, &root_handle, &root_pub_out)) {
   167      printf("CreatePrimary root succeeded\n");
   168    } else {
   169      printf("CreatePrimary root failed\n");
   170      ret_val = 1;
   171      goto done;
   172    }
   173  
   174    *(uint32_t*)(&seal_create_flags) = 0;
   175    seal_create_flags.fixedTPM = 1;
   176    seal_create_flags.fixedParent = 1;
   177    seal_create_flags.sensitiveDataOrigin = 1;
   178    seal_create_flags.userWithAuth = 1;
   179    seal_create_flags.sign = 1;
   180  
   181    if (Tpm2_CreateKey(tpm, root_handle, parentAuth, authString, pcrSelect,
   182                       TPM_ALG_RSA, hash_alg_id, seal_create_flags, TPM_ALG_NULL,
   183                       (TPMI_AES_KEY_BITS)0, TPM_ALG_ECB, TPM_ALG_RSASSA,
   184                       2048, 0x010001, &seal_size_public, seal_out_public,
   185                       &seal_size_private, seal_out_private,
   186                       &creation_out, &digest_out, &creation_ticket)) {
   187      printf("Create seal key succeeded private size: %d, public size: %d\n",
   188             seal_size_private, seal_size_public);
   189    } else {
   190      printf("Create seal key failed\n");
   191      ret_val = 1;
   192      goto done;
   193    }
   194  
   195    // load seal key
   196    if (Tpm2_Load(tpm, root_handle, parentAuth, seal_size_public,
   197                  seal_out_public, seal_size_private, seal_out_private,
   198                  &seal_load_handle, &seal_name)) {
   199      printf("Load seal key succeeded\n");
   200    } else {
   201      printf("Load seal key failed\n");
   202      ret_val = 1;
   203      goto done;
   204    }
   205  
   206    *(uint32_t*)(&quote_create_flags) = 0;
   207    quote_create_flags.fixedTPM = 1;
   208    quote_create_flags.fixedParent = 1;
   209    quote_create_flags.sensitiveDataOrigin = 1;
   210    quote_create_flags.userWithAuth = 1;
   211    quote_create_flags.sign = 1;
   212    quote_create_flags.restricted = 1;
   213  
   214    if (Tpm2_CreateKey(tpm, root_handle, parentAuth, authString, pcrSelect,
   215                       TPM_ALG_RSA, hash_alg_id, quote_create_flags, TPM_ALG_NULL,
   216                       (TPMI_AES_KEY_BITS)0, TPM_ALG_ECB, TPM_ALG_RSASSA,
   217                       1024, 0x010001,
   218                       &quote_size_public, quote_out_public,
   219                       &quote_size_private, quote_out_private,
   220                       &creation_out, &digest_out, &creation_ticket)) {
   221      printf("Create quote succeeded, private size: %d, public size: %d\n",
   222             quote_size_private, quote_size_public);
   223    } else {
   224      printf("Create quote failed\n");
   225      ret_val = 1;
   226      goto done;
   227    }
   228  
   229    if (Tpm2_Load(tpm, root_handle, parentAuth, quote_size_public,
   230                  quote_out_public, quote_size_private, quote_out_private,
   231                  &quote_load_handle, &quote_name)) {
   232      printf("Load quote succeeded\n");
   233    } else {
   234      printf("Load quote failed\n");
   235      ret_val = 1;
   236      goto done;
   237    }
   238  
   239    // Save context primary context
   240    nv_handle = GetNvHandle(FLAGS_slot_primary);
   241    context_data_size = MAX_SIZE_PARAMS;
   242    if (!Tpm2_SaveContext(tpm, root_handle, &context_data_size,
   243                          context_save_area)) {
   244      printf("Primary SaveContext failed\n");
   245      ret_val = 1;
   246      goto done;
   247    }
   248  
   249  #ifdef DEBUG
   250    printf("Primary Save context worked, size is %d\n", context_data_size);
   251    printf("nv_handle: %08x\n", nv_handle);
   252    printf("Context save area (%d): ", context_data_size);
   253  #endif
   254  #ifdef DEBUG_EXTRA
   255    PrintBytes(context_data_size, context_save_area);
   256    printf("\n");
   257  #endif
   258    if (!Tpm2_UndefineSpace(tpm, TPM_RH_OWNER, nv_handle)) {
   259      printf("Primary UndefinedSpace failed\n");
   260    }
   261    // TODO(jlm): should be pcrpolicy protected
   262    // TODO(jlm): index into structures should be added 
   263    if (!Tpm2_DefineSpace(tpm, TPM_RH_OWNER, nv_handle, authString, 0, nullptr,
   264  			NV_AUTHWRITE | NV_AUTHREAD, (uint16_t)context_data_size + 32)) {
   265      printf("Primary DefinedSpace failed\n");
   266      ret_val = 1;
   267      goto done;
   268    }
   269  
   270  #ifdef DEBUG
   271    printf("Root writing %d bytes\n", context_data_size);
   272  #endif
   273  
   274    if (!Tpm2_WriteNv(tpm, nv_handle, authString, 
   275                      (uint16_t)context_data_size, context_save_area)){
   276      printf("Primary WriteNv failed\n");
   277      ret_val = 1;
   278      goto done;
   279    }
   280  
   281    // Save seal context
   282    nv_handle = GetNvHandle(FLAGS_slot_seal);
   283    context_data_size = MAX_SIZE_PARAMS;
   284    if (!Tpm2_SaveContext(tpm, seal_load_handle, &context_data_size,
   285                          context_save_area)) {
   286      printf("Seal SaveContext failed\n");
   287      ret_val = 1;
   288      goto done;
   289    }
   290  
   291  #ifdef DEBUG
   292    printf("Seal Save context worked, size is %d\n", context_data_size);
   293    printf("nv_handle: %08x\n", nv_handle);
   294  #endif
   295  
   296    if (!Tpm2_UndefineSpace(tpm, TPM_RH_OWNER, nv_handle)) {
   297      printf("Seal UndefinedSpace failed\n");
   298    }
   299    // TODO(jlm): should be pcrpolicy protected
   300    // TODO(jlm): index into structures should be added 
   301    if (!Tpm2_DefineSpace(tpm, TPM_RH_OWNER, nv_handle, authString, 0, nullptr,
   302                          NV_AUTHWRITE | NV_AUTHREAD, (uint16_t)context_data_size + 32)) {
   303      printf("Seal DefinedSpace failed\n");
   304      ret_val = 1;
   305      goto done;
   306    }
   307  
   308  #ifdef DEBUG
   309    printf("Seal writing %d bytes\n", context_data_size);
   310  #endif
   311    if (!Tpm2_WriteNv(tpm, nv_handle, authString, 
   312                      (uint16_t)context_data_size, context_save_area)){
   313      printf("Seal WriteNv failed\n");
   314      ret_val = 1;
   315      goto done;
   316    }
   317  
   318    // Save quote context
   319    nv_handle = GetNvHandle(FLAGS_slot_quote);
   320    context_data_size = MAX_SIZE_PARAMS;
   321    if (!Tpm2_SaveContext(tpm, quote_load_handle, &context_data_size,
   322                          context_save_area)) {
   323      printf("Quote SaveContext failed\n");
   324      ret_val = 1;
   325      goto done;
   326    }
   327  
   328  #ifdef DEBUG1
   329    printf("Quote SaveContext worked, size is %d\n", context_data_size);
   330    printf("nv_handle: %08x\n", nv_handle);
   331  #endif
   332  
   333    if (!Tpm2_UndefineSpace(tpm, TPM_RH_OWNER, nv_handle)) {
   334      printf("Seal UndefinedSpace failed\n");
   335    }
   336    // TODO(jlm): should be pcrpolicy protected
   337    // TODO(jlm): index into structures should be added 
   338    if (!Tpm2_DefineSpace(tpm, TPM_RH_OWNER, nv_handle, authString, 
   339  			0, nullptr, NV_AUTHWRITE | NV_AUTHREAD,
   340                          (uint16_t)context_data_size + 32)) {
   341      printf("Seal DefinedSpace failed\n");
   342      ret_val = 1;
   343      goto done;
   344    }
   345    printf("Quote writing %d bytes\n", context_data_size);
   346    if (!Tpm2_WriteNv(tpm, nv_handle, authString, 
   347                      (uint16_t)context_data_size, context_save_area)){
   348      printf("Seal WriteNv failed\n");
   349      ret_val = 1;
   350      goto done;
   351    }
   352  
   353  done:
   354    if (root_handle != 0) {
   355      Tpm2_FlushContext(tpm, root_handle);
   356    }
   357    if (seal_load_handle != 0) {
   358      Tpm2_FlushContext(tpm, seal_load_handle);
   359    }
   360    if (quote_load_handle != 0) {
   361      Tpm2_FlushContext(tpm, quote_load_handle);
   362    }
   363    if (sealed_load_handle != 0) {
   364      Tpm2_FlushContext(tpm, sealed_load_handle);
   365    }
   366    tpm.CloseTpm();
   367    return ret_val;
   368  }
   369