github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/src/tpm2/CloudProxySignEndorsementKey.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/err.h>
    10  #include <openssl/rand.h>
    11  #include <openssl/ssl.h>
    12  #include <openssl/rsa.h>
    13  #include <openssl_helpers.h>
    14  
    15  #include <tpm20.h>
    16  #include <tpm2_lib.h>
    17  #include <tpm2.pb.h>
    18  #include <gflags/gflags.h>
    19  
    20  //
    21  // Copyright 2015 Google Corporation, All Rights Reserved.
    22  //
    23  // Licensed under the Apache License, Version 2.0 (the "License");
    24  // you may not use this file except in compliance with the License.
    25  // You may obtain a copy of the License at
    26  //     http://www.apache.org/licenses/LICENSE-2.0
    27  // or in the the file LICENSE-2.0.txt in the top level sourcedirectory
    28  // Unless required by applicable law or agreed to in writing, software
    29  // distributed under the License is distributed on an "AS IS" BASIS,
    30  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    31  // See the License for the specific language governing permissions and
    32  // limitations under the License
    33  //
    34  // Portions of this code were derived TPM2.0-TSS published
    35  // by Intel under the license set forth in intel_license.txt
    36  // and downloaded on or about August 6, 2015.
    37  // Portions of this code were derived tboot published
    38  // by Intel under the license set forth in intel_license.txt
    39  // and downloaded on or about August 6, 2015.
    40  // Portions of this code were derived from the crypto utility
    41  // published by John Manferdelli under the Apache 2.0 license.
    42  // See github.com/jlmucb/crypto.
    43  // File: CloudProxySignEndorsementKey.cc
    44  
    45  
    46  // Calling sequence
    47  //   CloudProxySignEndorsementKey.exe --cloudproxy_private_key_file=file-name [IN]
    48  //       --endorsement_info_file=file-name [IN]
    49  //       --signing_instructions_file=file-name [IN]
    50  //       --signed_endorsement_cert=file-name [OUT]
    51  
    52  using std::string;
    53  
    54  //  This program reads the endorsement_info_file and sogns a certificate
    55  //  for the endorsement key using the cloudproxy_signing_key in accordance with
    56  //  the signing instructions.  signing instructions contains a subset of:
    57  //  duration, purpose, and other information to be included in the 
    58  //  signed certificate.
    59  
    60  
    61  #define MAX_BUF_SIZE 8192
    62  
    63  #define CALLING_SEQUENCE "Calling secquence: CloudProxySignEndorsementKey.exe" \
    64  "--cloudproxy_private_key_file=input-file-name" \
    65  "--endorsement_info_file=file-name  --signing_instructions_file=input-file-name" \
    66  "--signed_endorsement_cert=output-file-name\n"
    67  
    68  void PrintOptions() {
    69    printf(CALLING_SEQUENCE);
    70  }
    71  
    72  DEFINE_string(endorsement_info_file, "", "output file");
    73  DEFINE_string(cloudproxy_private_key_file, "", "private key file");
    74  DEFINE_string(signing_instructions_file, "", "signing instructions file");
    75  DEFINE_string(signed_endorsement_cert, "", "signed endorsement cert file");
    76  
    77  #ifndef GFLAGS_NS
    78  #define GFLAGS_NS google
    79  #endif
    80  
    81  #define DEBUG
    82  
    83  int main(int an, char** av) {
    84    int ret_val = 0;
    85  
    86    printf("\nCloudProxySignEndorsementKey\n\n");
    87  
    88    GFLAGS_NS::ParseCommandLineFlags(&an, &av, true);
    89    OpenSSL_add_all_algorithms();
    90    ERR_load_crypto_strings();
    91    
    92    if (FLAGS_signing_instructions_file == "") {
    93      printf("signing_instructions_file is empty\n");
    94      return 1;
    95    }
    96    if (FLAGS_endorsement_info_file == "") {
    97      printf("endorsement_info_file is empty\n");
    98      return 1;
    99    }
   100    if (FLAGS_cloudproxy_private_key_file == "") {
   101      printf("cloudproxy_private_key_file is empty\n");
   102      return 1;
   103    }
   104    if (FLAGS_signed_endorsement_cert == "") {
   105      printf("signed_endorsement_cert is empty\n");
   106      return 1;
   107    }
   108  
   109    int in_size = MAX_BUF_SIZE;
   110    byte in_buf[MAX_BUF_SIZE];
   111  
   112    string input;
   113    signing_instructions_message signing_message;
   114    if (!ReadFileIntoBlock(FLAGS_signing_instructions_file, &in_size, 
   115                           in_buf)) {
   116      printf("Can't read signing instructions %s\n",
   117             FLAGS_signing_instructions_file.c_str());
   118      return 1;
   119    }
   120    input.assign((const char*)in_buf, in_size);
   121    if (!signing_message.ParseFromString(input)) {
   122      printf("Can't parse signing instructions\n");
   123      return 1;
   124    }
   125  #ifdef DEBUG
   126    printf("issuer: %s, duration: %ld, purpose: %s, hash: %s\n",
   127           signing_message.issuer().c_str(), (long)signing_message.duration(),
   128           signing_message.purpose().c_str(), signing_message.hash_alg().c_str());
   129  #endif
   130    
   131    if (!signing_message.can_sign()) {
   132      printf("Signing is invalid\n");
   133      return 1;
   134    }
   135  
   136    in_size = MAX_BUF_SIZE;
   137    endorsement_key_message endorsement_info;
   138    if (!ReadFileIntoBlock(FLAGS_endorsement_info_file, &in_size, in_buf)) {
   139      printf("Can't read endorsement info\n");
   140      return 1;
   141    }
   142    input.assign((const char*)in_buf, in_size);
   143    if (!endorsement_info.ParseFromString(input)) {
   144      printf("Can't parse endorsement info\n");
   145      return 1;
   146    }
   147  
   148    in_size = MAX_BUF_SIZE;
   149    private_key_blob_message private_key;
   150    if (!ReadFileIntoBlock(FLAGS_cloudproxy_private_key_file, &in_size, 
   151                           in_buf)) {
   152      printf("Can't read private key\n");
   153      printf("    %s\n", FLAGS_cloudproxy_private_key_file.c_str());
   154      return 1;
   155    }
   156    input.assign((const char*)in_buf, in_size);
   157    if (!private_key.ParseFromString(input)) {
   158      printf("Can't parse private key\n");
   159      return 1;
   160    }
   161  
   162  #ifdef DEBUG
   163    printf("\nPolicy key type: %s\n", private_key.key_type().c_str());
   164    printf("Policy key name: %s\n\n", private_key.key_name().c_str());
   165  #endif
   166  
   167    string the_blob = private_key.blob();
   168    PrintBytes(the_blob.size(), (byte*)the_blob.data());
   169    const byte* p = (byte*)the_blob.data();
   170    RSA* signing_key = d2i_RSAPrivateKey(nullptr, &p, the_blob.size());
   171    if (signing_key == nullptr) {
   172      printf("Can't translate private key\n");
   173      return 1;
   174    }
   175  #ifdef DEBUG
   176    print_internal_private_key(*signing_key);
   177  #endif
   178  
   179    string key_blob = endorsement_info.tpm2b_blob();
   180    uint16_t size_in;
   181    ChangeEndian16((uint16_t*)key_blob.data(), (uint16_t*)&size_in);
   182    TPM2B_PUBLIC outPublic;
   183    if (!GetReadPublicOut(size_in, (byte*)(key_blob.data() + sizeof(uint16_t)),
   184                          &outPublic)) {
   185      printf("Can't parse endorsement blob\n");
   186      return 1;
   187    }
   188  
   189  #ifdef DEBUG
   190    printf("\nEndorsement key size: %d\n",
   191           (int)outPublic.publicArea.unique.rsa.size * 8);
   192    printf("Endorsement key modulus: ");
   193    PrintBytes((int)outPublic.publicArea.unique.rsa.size,
   194               outPublic.publicArea.unique.rsa.buffer);
   195    printf("\n\n");
   196  #endif
   197  
   198    // fill x509_cert_request_parameters_message
   199    x509_cert_request_parameters_message req_message;
   200    req_message.set_common_name(endorsement_info.machine_identifier());
   201    // country_name state_name locality_name organization_name
   202    //      suborganization_name
   203    req_message.mutable_key()->set_key_type("RSA");
   204    req_message.mutable_key()->mutable_rsa_key()->set_bit_modulus_size(
   205        (int)outPublic.publicArea.unique.rsa.size * 8);
   206    uint64_t expIn = (uint64_t)
   207        outPublic.publicArea.parameters.rsaDetail.exponent;
   208    uint64_t expOut;
   209    ChangeEndian64((uint64_t*)&expIn, (uint64_t*)(&expOut));
   210  
   211    req_message.mutable_key()->mutable_rsa_key()->set_exponent(
   212        (const char*)&expOut, sizeof(uint64_t));
   213    req_message.mutable_key()->mutable_rsa_key()->set_modulus(
   214        (const char*)outPublic.publicArea.unique.rsa.buffer,
   215        (int)outPublic.publicArea.unique.rsa.size);
   216  
   217  #ifdef DEBUG
   218    printf("\nCert request:\n");
   219    print_cert_request_message(req_message); printf("\n");
   220  #endif
   221  
   222    EVP_PKEY* subject_key = EVP_PKEY_new();
   223    RSA* rsa_subject_key = RSA_new();
   224    rsa_subject_key->n = bin_to_BN((int)outPublic.publicArea.unique.rsa.size,
   225                                   outPublic.publicArea.unique.rsa.buffer);
   226    rsa_subject_key->e = bin_to_BN(sizeof(uint64_t), (byte*)&expOut);
   227    EVP_PKEY_assign_RSA(subject_key, rsa_subject_key);
   228  
   229    X509_REQ* req = X509_REQ_new();
   230    X509_REQ_set_version(req, 2);
   231    if (!GenerateX509CertificateRequest(req_message, false, req)) {
   232      printf("Can't generate x509 request\n");
   233      return 1;
   234    }
   235  
   236    // sign it
   237    X509* cert = X509_new();
   238    X509_set_pubkey(cert, subject_key);
   239    // X509_set_issuer_name(cert, issuerSubject)
   240    if (!SignX509Certificate(signing_key, false, signing_message, subject_key,
   241                             req, false, cert)) {
   242      printf("Can't sign x509 request\n");
   243      return 1;
   244    }
   245  
   246  #ifdef DEBUG
   247    printf("message signed\n");
   248  #endif
   249  
   250    byte* out = nullptr;
   251    int size = i2d_X509(cert, &out);
   252    string output;
   253    output.assign((const char*)out, size);
   254    if (!WriteFileFromBlock(FLAGS_signed_endorsement_cert,
   255                            output.size(),
   256                            (byte*)output.data())) {
   257      printf("Can't write endorsement cert\n");
   258      return 1;
   259    }
   260    return ret_val;
   261  }
   262