github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/src/tpm2/ServerSignProgramKeyRequest.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 <openssl/aes.h> 10 #include <openssl/rsa.h> 11 #include <openssl/x509.h> 12 #include <openssl_helpers.h> 13 #include <openssl/rand.h> 14 #include <openssl/hmac.h> 15 #include <openssl/sha.h> 16 17 #include <openssl_helpers.h> 18 #include <quote_protocol.h> 19 20 #include <tpm20.h> 21 #include <tpm2_lib.h> 22 #include <gflags/gflags.h> 23 24 // 25 // Copyright 2015 Google Corporation, All Rights Reserved. 26 // 27 // Licensed under the Apache License, Version 2.0 (the "License"); 28 // you may not use this file except in compliance with the License. 29 // You may obtain a copy of the License at 30 // http://www.apache.org/licenses/LICENSE-2.0 31 // or in the the file LICENSE-2.0.txt in the top level sourcedirectory 32 // Unless required by applicable law or agreed to in writing, software 33 // distributed under the License is distributed on an "AS IS" BASIS, 34 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 35 // See the License for the specific language governing permissions and 36 // limitations under the License 37 // 38 // Portions of this code were derived TPM2.0-TSS published 39 // by Intel under the license set forth in intel_license.txt 40 // and downloaded on or about August 6, 2015. 41 // Portions of this code were derived tboot published 42 // by Intel under the license set forth in intel_license.txt 43 // and downloaded on or about August 6, 2015. 44 // Portions of this code were derived from the crypto utility 45 // published by John Manferdelli under the Apache 2.0 license. 46 // See github.com/jlmucb/crypto. 47 // File: ServerSignProgramKeyRequest.cc 48 49 50 // This program verifies endorsement cert, quote key and signature. 51 // It then constructs and signs an x509 cert for the proposed 52 // program key. It encrypts the signed cert to the Endorsement Key 53 // referencing the Quote Key and creates the decrypt information 54 // required by ActivateCredential. It saves the encrypted 55 // information in the response file. 56 57 // Calling sequence: ServerSignProgramKeyRequest.exe 58 // --program_cert_request_file=input-file-name 59 // --program_cert_response_file=output-file-name 60 61 62 using std::string; 63 64 65 #define CALLING_SEQUENCE "ServerSignProgramKeyRequest.exe " \ 66 "--signing_instructions_file=input-file" \ 67 "--cloudproxy_key_file=input-file" \ 68 "--program_cert_request_file=output-file-name " \ 69 "--program_response_file=output-file-name" 70 71 void PrintOptions() { 72 printf("Calling sequence: %s", CALLING_SEQUENCE); 73 } 74 75 DEFINE_string(signed_endorsement_cert_file, "", "input-file-name"); 76 DEFINE_string(signing_instructions_file, "", "input-file-name"); 77 DEFINE_string(program_cert_request_file, "", "input-file-name"); 78 // TODO(jlm): policy file should contain list of approved pcrs 79 DEFINE_string(hash_alg, "sha1", "hash-function"); 80 DEFINE_string(policy_file, "", "input-file-name"); 81 DEFINE_string(policy_cert_file, "policy_cert_file", "input-file-name"); 82 DEFINE_string(policy_identifier, "cloudproxy", "policy domain name"); 83 DEFINE_string(cloudproxy_key_file, "", "input-file-name"); 84 DEFINE_string(program_response_file, "", "output-file-name"); 85 86 #ifndef GFLAGS_NS 87 #define GFLAGS_NS google 88 #endif 89 90 #define MAX_SIZE_PARAMS 8192 91 92 // magic constant for tpm generated 93 #define TpmMagicConstant 0xff544347 94 95 // Consults policy database to confirm pcr's are OK 96 bool ValidPCR(TPM_ALG_ID hash, byte* pcr_selection, byte* digest) { 97 return true; 98 } 99 100 int main(int an, char** av) { 101 int ret_val = 0; 102 103 printf("\nServerSignProgramKeyRequest\n\n"); 104 105 GFLAGS_NS::ParseCommandLineFlags(&an, &av, true); 106 107 int size_cert_request = MAX_SIZE_PARAMS; 108 byte cert_request_buf[MAX_SIZE_PARAMS]; 109 x509_cert_request_parameters_message cert_request; 110 111 int in_size = MAX_SIZE_PARAMS; 112 byte in_buf[MAX_SIZE_PARAMS]; 113 114 X509_REQ* req = nullptr; 115 X509* program_cert = nullptr; 116 X509* policy_cert = nullptr; 117 X509* endorsement_cert = nullptr; 118 X509_STORE_CTX* verify_ctx = nullptr; 119 120 TPM2B_DIGEST unmarshaled_credential; 121 TPM2B_DIGEST marshaled_credential; 122 TPM2B_NAME unmarshaled_name; 123 TPM2B_NAME marshaled_name; 124 TPM2B_DIGEST unmarshaled_integrityHmac; 125 TPM2B_DIGEST marshaled_integrityHmac; 126 TPM2B_ENCRYPTED_SECRET unmarshaled_encrypted_secret; 127 TPM2B_ENCRYPTED_SECRET marshaled_encrypted_secret; 128 int size_hmac = MAX_SIZE_PARAMS; 129 byte encrypted_data_hmac[MAX_SIZE_PARAMS]; 130 int size_encrypted_data = MAX_SIZE_PARAMS; 131 byte encrypted_data[MAX_SIZE_PARAMS]; 132 int size_encIdentity = MAX_SIZE_PARAMS; 133 byte encIdentity[MAX_SIZE_PARAMS]; 134 135 TPM_ALG_ID hash_alg_id; 136 if (FLAGS_hash_alg == "sha1") { 137 hash_alg_id = TPM_ALG_SHA1; 138 } else if (FLAGS_hash_alg == "sha256") { 139 hash_alg_id = TPM_ALG_SHA256; 140 } else { 141 printf("Unknown hash algorithm\n"); 142 return 1; 143 } 144 145 int size_quote_out; 146 147 byte* der_program_cert = nullptr; 148 int der_program_cert_size = 0; 149 byte der_policy_cert[MAX_SIZE_PARAMS]; 150 int der_policy_cert_size = MAX_SIZE_PARAMS; 151 byte* endorsement_blob = nullptr; 152 int endorsement_blob_size; 153 program_cert = X509_new(); 154 byte program_key_quoted_hash[256]; 155 int signed_quote_hash_size = 0; 156 byte signed_quote_hash[MAX_SIZE_PARAMS]; 157 int quote_struct_size = 0; 158 byte quote_struct[MAX_SIZE_PARAMS]; 159 byte decrypted_quote[MAX_SIZE_PARAMS]; 160 161 private_key_blob_message private_key; 162 program_cert_request_message request; 163 program_cert_response_message response; 164 signing_instructions_message signing_message; 165 x509_cert_request_parameters_message cert_parameters; 166 167 int cert_OK = 0; 168 byte* p_byte = nullptr; 169 170 string name; 171 string input; 172 string output; 173 string private_key_blob; 174 175 SHA_CTX sha1; 176 SHA256_CTX sha256; 177 RSA* signing_key = nullptr; 178 byte* signing_blob = nullptr; 179 RSA* quote_key = RSA_new(); 180 TPMS_ATTEST attested_quote; 181 string serialized_program_key; 182 183 if (FLAGS_signing_instructions_file == "") { 184 printf("signing_instructions_file is empty\n"); 185 ret_val = 1; 186 goto done; 187 } 188 if (FLAGS_program_cert_request_file == "") { 189 printf("program_cert_request_file is empty\n"); 190 ret_val = 1; 191 goto done; 192 } 193 if (FLAGS_cloudproxy_key_file == "") { 194 printf("cloudproxy_key_file is empty\n"); 195 ret_val = 1; 196 goto done; 197 } 198 if (FLAGS_program_response_file == "") { 199 printf("program_response_file is empty\n"); 200 ret_val = 1; 201 goto done; 202 } 203 204 OpenSSL_add_all_algorithms(); 205 206 // Get request 207 if (!ReadFileIntoBlock(FLAGS_program_cert_request_file, &size_cert_request, 208 cert_request_buf)) { 209 printf("Can't read cert request\n"); 210 ret_val = 1; 211 goto done; 212 } 213 214 #ifdef DEBUG 215 printf("Program cert request (%d): ", size_cert_request); 216 PrintBytes(size_cert_request, cert_request_buf); 217 printf("\n"); 218 #endif 219 220 input.assign((const char*)cert_request_buf, size_cert_request); 221 if (!request.ParseFromString(input)) { 222 printf("Can't parse cert request\n"); 223 ret_val = 1; 224 goto done; 225 } 226 227 // Get signing instructions 228 if (!ReadFileIntoBlock(FLAGS_signing_instructions_file, &in_size, in_buf)) { 229 printf("Can't read signing instructions %s\n", 230 FLAGS_signing_instructions_file.c_str()); 231 ret_val = 1; 232 goto done; 233 } 234 input.assign((const char*)in_buf, in_size); 235 if (!signing_message.ParseFromString(input)) { 236 printf("Can't parse signing instructions\n"); 237 ret_val = 1; 238 goto done; 239 } 240 printf("issuer: %s, duration: %ld, purpose: %s, hash: %s\n", 241 signing_message.issuer().c_str(), (long)signing_message.duration(), 242 signing_message.purpose().c_str(), signing_message.hash_alg().c_str()); 243 if (!signing_message.can_sign()) { 244 printf("Signing is invalid\n"); 245 ret_val = 1; 246 goto done; 247 } 248 249 // Get cloudproxy key 250 in_size = MAX_SIZE_PARAMS; 251 if (!ReadFileIntoBlock(FLAGS_cloudproxy_key_file, &in_size, in_buf)) { 252 printf("Can't read private key\n"); 253 printf(" %s\n", FLAGS_cloudproxy_key_file.c_str()); 254 } 255 input.assign((const char*)in_buf, in_size); 256 if (!private_key.ParseFromString(input)) { 257 printf("Can't parse private key\n"); 258 } 259 260 private_key_blob = private_key.blob(); 261 PrintBytes(private_key_blob.size(), (byte*)private_key_blob.data()); 262 printf("\n"); 263 signing_blob = (byte*)private_key_blob.data(); 264 p_byte = signing_blob; 265 signing_key = d2i_RSAPrivateKey(nullptr, (const byte**)&p_byte, 266 private_key_blob.size()); 267 if (signing_key == nullptr) { 268 printf("Can't translate private key\n"); 269 ret_val = 1; 270 goto done; 271 } 272 273 #ifdef DEBUG 274 print_internal_private_key(*signing_key); 275 #endif 276 277 // Extract program key request 278 if (!request.has_quote_key_info()) { 279 printf("No information to construct cred\n"); 280 ret_val = 1; 281 goto done; 282 } 283 284 // Get Policy cert 285 if (!ReadFileIntoBlock(FLAGS_policy_cert_file, &der_policy_cert_size, 286 der_policy_cert)) { 287 printf("Can't read policy cert \n"); 288 ret_val = 1; 289 goto done; 290 } 291 292 // Get endorsement cert 293 endorsement_blob = (byte*)request.endorsement_cert_blob().data(); 294 endorsement_blob_size = request.endorsement_cert_blob().size(); 295 296 p_byte = der_policy_cert; 297 policy_cert = d2i_X509(nullptr, (const byte**)&p_byte, 298 der_policy_cert_size); 299 if (policy_cert == nullptr) { 300 printf("Can't convert policy cert\n"); 301 ret_val = 1; 302 goto done; 303 } 304 305 // Verify endorsement cert 306 p_byte = endorsement_blob; 307 endorsement_cert = d2i_X509(nullptr, (const byte**)&p_byte, 308 endorsement_blob_size); 309 if ((verify_ctx = X509_STORE_CTX_new()) == nullptr) { 310 printf("Can't new X509_STORE_CTX\n"); 311 ret_val = 1; 312 goto done; 313 } 314 cert_OK = X509_verify(endorsement_cert, X509_get_pubkey(policy_cert)); 315 if (cert_OK <= 0) { 316 printf("Endorsement cert does not verivy\n"); 317 ret_val = 1; 318 goto done; 319 } 320 321 // Generate request for program cert 322 cert_parameters.set_common_name(request.program_key().program_name()); 323 cert_parameters.mutable_key()->set_key_type(request.program_key().program_key_type()); 324 cert_parameters.mutable_key()->mutable_rsa_key()->set_bit_modulus_size( 325 request.program_key().program_bit_modulus_size()); 326 cert_parameters.mutable_key()->mutable_rsa_key()->set_exponent( 327 request.program_key().program_key_exponent()); 328 cert_parameters.mutable_key()->mutable_rsa_key()->set_modulus( 329 request.program_key().program_key_modulus()); 330 print_cert_request_message(cert_parameters); printf("\n"); 331 332 req = X509_REQ_new(); 333 if (!GenerateX509CertificateRequest(cert_parameters, false, req)) { 334 printf("Can't generate certificate request\n"); 335 ret_val = 1; 336 goto done; 337 } 338 339 // sign program key 340 if (!SignX509Certificate(signing_key, false, signing_message, nullptr, req, 341 false, program_cert)) { 342 printf("Can't sign x509 request for program key\n"); 343 ret_val = 1; 344 goto done; 345 } 346 printf("\nmessage signed\n"); 347 348 // Serialize program cert 349 der_program_cert = nullptr; 350 der_program_cert_size = i2d_X509(program_cert, &der_program_cert); 351 352 #ifdef DEBUG 353 printf("Program cert: "); 354 PrintBytes(der_program_cert_size, der_program_cert); printf("\n"); 355 X509_print_fp(stdout, program_cert); 356 printf("\n"); 357 #endif 358 359 // Hash request 360 serialized_program_key = request.program_key().DebugString(); 361 if (hash_alg_id == TPM_ALG_SHA1) { 362 SHA1_Init(&sha1); 363 SHA1_Update(&sha1, (byte*)serialized_program_key.data(), 364 serialized_program_key.size()); 365 SHA1_Final(program_key_quoted_hash, &sha1); 366 } else if (hash_alg_id == TPM_ALG_SHA256) { 367 SHA256_Init(&sha256); 368 SHA256_Update(&sha256, (byte*)serialized_program_key.data(), 369 serialized_program_key.size()); 370 SHA256_Final(program_key_quoted_hash, &sha256); 371 } else { 372 printf("Unknown hash alg\n"); 373 ret_val = 1; 374 goto done; 375 } 376 377 #ifdef DEBUG 378 printf("\nprogram_key_quoted_hash: "); 379 PrintBytes(SizeHash(hash_alg_id), program_key_quoted_hash); 380 printf("\n"); 381 #endif 382 383 // "Encrypt" with quote key to verify 384 if (!request.quote_key_info().has_public_key()) { 385 printf("no quote key\n"); 386 ret_val = 1; 387 goto done; 388 } 389 390 quote_struct_size = request.quoted_blob().size(); 391 memcpy(quote_struct, request.quoted_blob().data(), quote_struct_size); 392 393 #ifdef DEBUG_EXTRA 394 printf("\nmodulus size: %d\n", 395 (int)request.quote_key_info().public_key().rsa_key().modulus().size()); 396 printf("exponent size: %d\n", 397 (int)request.quote_key_info().public_key().rsa_key().exponent().size()); 398 printf("modulus: "); 399 PrintBytes(request.quote_key_info().public_key().rsa_key().modulus().size(), 400 (byte*)request.quote_key_info().public_key().rsa_key().modulus().data()); 401 printf("\n"); 402 printf("exponent: "); 403 PrintBytes(request.quote_key_info().public_key().rsa_key().exponent().size(), 404 (byte*)request.quote_key_info().public_key().rsa_key().exponent().data()); 405 printf("\n"); 406 printf("quote_struct: "); 407 PrintBytes(quote_struct_size, quote_struct); 408 printf("\n"); 409 #endif 410 411 // Decode quote structure 412 if (!UnmarshalCertifyInfo(quote_struct_size, quote_struct, &attested_quote)) { 413 printf("Invalid attested structure\n"); 414 ret_val = 1; 415 goto done; 416 } 417 if (attested_quote.magic != TpmMagicConstant) { 418 printf("Invalid magic number\n"); 419 ret_val = 1; 420 goto done; 421 } 422 423 if(!ValidPCR(attested_quote.attested.quote.pcrSelect.pcrSelections[0].hash, 424 &attested_quote.attested.quote.pcrSelect.pcrSelections[0].sizeofSelect, 425 attested_quote.attested.quote.pcrDigest.buffer)) { 426 printf("Invalid pcr\n"); 427 ret_val = 1; 428 goto done; 429 } 430 431 // Set quote key exponent and modulus 432 quote_key->n = bin_to_BN( 433 request.quote_key_info().public_key().rsa_key().modulus().size(), 434 (byte*)request.quote_key_info().public_key().rsa_key().modulus().data()); 435 quote_key->e = bin_to_BN( 436 request.quote_key_info().public_key().rsa_key().exponent().size(), 437 (byte*)request.quote_key_info().public_key().rsa_key().exponent().data()); 438 size_quote_out = RSA_public_encrypt(request.quote_signature().size(), 439 (const byte*)request.quote_signature().data(), 440 decrypted_quote, quote_key, RSA_NO_PADDING); 441 if (size_quote_out > MAX_SIZE_PARAMS) { 442 printf("quote signature is too big\n"); 443 ret_val = 1; 444 goto done; 445 } 446 signed_quote_hash_size = MAX_SIZE_PARAMS; 447 if (!ComputeQuotedValue(hash_alg_id, quote_struct_size, quote_struct, 448 &signed_quote_hash_size, signed_quote_hash)) { 449 printf("Cant compute ComputeQuotedValue\n"); 450 ret_val = 1; 451 goto done; 452 } 453 454 // Check hash of request 455 if (memcmp(attested_quote.extraData.buffer, program_key_quoted_hash, 456 attested_quote.extraData.size) != 0) { 457 printf("Program key hash does not match\n"); 458 ret_val = 1; 459 goto done; 460 } 461 462 #ifdef DEBUG 463 printf("\nquote signature size: %d\n", size_quote_out); 464 printf("Quote structure: "); 465 PrintBytes(quote_struct_size, quote_struct); 466 printf("\n"); 467 printf("Quote hash: "); 468 PrintBytes(signed_quote_hash_size, signed_quote_hash); 469 printf("\n"); 470 printf("Decrypted hash: "); 471 PrintBytes(size_quote_out, decrypted_quote); 472 printf("\n"); 473 #endif 474 475 // recover pcr hash and magic number and check them 476 // Compare signature and computed hash 477 if (memcmp(signed_quote_hash, 478 decrypted_quote + size_quote_out - SizeHash(hash_alg_id), 479 SizeHash(hash_alg_id)) != 0) { 480 printf("quote signature is wrong\n"); 481 PrintBytes(SizeHash(hash_alg_id), signed_quote_hash); printf("\n"); 482 PrintBytes(size_quote_out, decrypted_quote); printf("\n"); 483 ret_val = 1; 484 goto done; 485 } 486 487 // Prepare encrypted secret, 488 489 // Generate encryption key for signed program cert 490 // This is the "credential." 491 unmarshaled_credential.size = 16; 492 RAND_bytes(unmarshaled_credential.buffer, unmarshaled_credential.size); 493 ChangeEndian16(&unmarshaled_credential.size, &marshaled_credential.size); 494 memcpy(marshaled_credential.buffer, unmarshaled_credential.buffer, 495 unmarshaled_credential.size); 496 unmarshaled_name.size = request.quote_key_info().name().size(); 497 memcpy(unmarshaled_name.name, (byte*)request.quote_key_info().name().data(), 498 unmarshaled_name.size); 499 ChangeEndian16(&unmarshaled_name.size, &marshaled_name.size); 500 memcpy(marshaled_name.name, unmarshaled_name.name, unmarshaled_name.size); 501 printf("Quote name : ");PrintBytes(unmarshaled_name.size, unmarshaled_name.name); printf("\n"); 502 503 // Encrypt signed program cert and prepare ActivateCredential buffer 504 if (!MakeCredential(endorsement_blob_size, endorsement_blob, 505 hash_alg_id, unmarshaled_credential, marshaled_credential, 506 unmarshaled_name, marshaled_name, 507 &size_encIdentity, encIdentity, 508 &unmarshaled_encrypted_secret, &marshaled_encrypted_secret, 509 &unmarshaled_integrityHmac, &marshaled_integrityHmac)) { 510 printf("MakeCredential failed\n"); 511 ret_val = 1; 512 goto done; 513 } 514 515 if (!EncryptDataWithCredential(true, hash_alg_id, 516 unmarshaled_credential, marshaled_credential, 517 der_program_cert_size, der_program_cert, 518 &size_hmac, (byte*)encrypted_data_hmac, 519 &size_encrypted_data, encrypted_data)) { 520 printf("EncryptDataWithCredential failed\n"); 521 ret_val = 1; 522 goto done; 523 } 524 525 #ifdef DEBUG 526 printf("\ncredential secret: "); 527 PrintBytes(16, unmarshaled_credential.buffer); 528 printf("\n"); 529 printf("\nder_program_cert: "); 530 PrintBytes(der_program_cert_size, der_program_cert); 531 printf("\n"); 532 printf("\nencrypted der_program_cert: "); 533 PrintBytes(der_program_cert_size, encrypted_data); 534 printf("\n"); 535 printf("der_program_cert_size: %d\n", der_program_cert_size); 536 printf("size_encrypted_data: %d\n", size_encrypted_data); 537 printf("\nencrypted secret: "); 538 PrintBytes(unmarshaled_encrypted_secret.size, unmarshaled_encrypted_secret.secret); 539 printf("\n"); 540 { 541 int size_decrypted_cert = MAX_SIZE_PARAMS; 542 byte decrypted_cert[MAX_SIZE_PARAMS]; 543 if (!EncryptDataWithCredential(false, hash_alg_id, 544 unmarshaled_credential, marshaled_credential, 545 size_encrypted_data, encrypted_data, 546 &size_hmac, (byte*) encrypted_data_hmac, 547 &size_decrypted_cert, decrypted_cert)) { 548 printf("EncryptDataWithCredential failed\n"); 549 } else { 550 printf("\ndecrypted der_program_cert: "); 551 PrintBytes(size_decrypted_cert, decrypted_cert); 552 printf("\n"); 553 } 554 if (size_decrypted_cert == der_program_cert_size && 555 memcmp(decrypted_cert, der_program_cert, size_decrypted_cert) == 0) { 556 printf("Original cert and decrypted cert match\n"); 557 } else { 558 printf("Original cert and decrypted cert DO NOT match\n"); 559 } 560 } 561 printf("\nhmac: "); 562 PrintBytes(unmarshaled_integrityHmac.size, unmarshaled_integrityHmac.buffer); 563 printf("\n"); 564 printf("\nencIdentity: "); 565 PrintBytes(size_encIdentity, encIdentity); 566 printf("\n"); 567 #endif 568 569 response.set_secret(marshaled_encrypted_secret.secret, 570 unmarshaled_encrypted_secret.size); 571 response.set_encidentity(encIdentity, size_encIdentity); 572 response.set_integrityhmac((byte*)&marshaled_integrityHmac, 573 unmarshaled_integrityHmac.size + sizeof(uint16_t)); 574 response.set_encrypted_cert_hmac((byte*) encrypted_data_hmac, size_hmac); 575 response.set_encrypted_cert(encrypted_data, size_encrypted_data); 576 577 #ifdef DEBUG 578 printf("\nmac'ed: "); 579 PrintBytes(response.encrypted_cert().size(), 580 (byte*)response.encrypted_cert().data()); 581 printf("\n"); 582 printf("\nmac : "); 583 PrintBytes(response.encrypted_cert_hmac().size(), 584 (byte*)response.encrypted_cert_hmac().data()); 585 printf("\n"); 586 #endif 587 588 // Serialize output 589 response.SerializeToString(&output); 590 if (!WriteFileFromBlock(FLAGS_program_response_file, 591 output.size(), 592 (byte*)output.data())) { 593 printf("Can't write endorsement cert\n"); 594 ret_val = 1; 595 goto done; 596 } 597 598 done: 599 return ret_val; 600 } 601 602