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