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*)("e_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 "e_size_public, quote_out_public, 219 "e_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 "e_load_handle, "e_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