github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/src/tpm2/SelfSignPolicyCert.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: SelfSignPolicyCert.cc
    44  
    45  
    46  // Calling sequence
    47  //   SelfSignPolicyCert.exe --signing_instructions=input-file 
    48  //     --key_file=input-file --policy_identifier=name --cert_file=output-file
    49  
    50  using std::string;
    51  
    52  // This program signs the policy key using the policy key.
    53  // The policy_identifier identifies the policy domain.
    54  
    55  DEFINE_string(signing_instructions_file, "", "signing_instructions");
    56  DEFINE_string(key_file, "", "key_input");
    57  DEFINE_string(policy_identifier, "", "text to identify policy domain");
    58  DEFINE_string(cert_file, "cert_file", "cert output file");
    59  
    60  #ifndef GFLAGS_NS
    61  #define GFLAGS_NS google
    62  #endif
    63  
    64  #define MAX_BUF_SIZE 8192
    65  
    66  void PrintOptions() {
    67    printf("Calling sequence: SelfSignPolicyCert.exe "\
    68  "--signing_instructions_file=input-file "\
    69  "--key_file=input-file --policy_identifier=name --cert_file=output-file\n");
    70  }
    71  
    72  int main(int an, char** av) {
    73    int ret_val = 0;
    74  
    75    printf("\nSelfSignPolicyCert\n\n");
    76  
    77    GFLAGS_NS::ParseCommandLineFlags(&an, &av, true);
    78    if (FLAGS_signing_instructions_file == "") {
    79      printf("You must specify a signing instructions file \n");
    80      PrintOptions();
    81      return 1;
    82    }
    83     if (FLAGS_key_file == "") {
    84      printf("key_file is empty\n");
    85      return 1;
    86    }
    87    if (FLAGS_policy_identifier == "") {
    88      printf("policy_identifier is empty\n");
    89      return 1;
    90    }
    91  
    92    int in_size = MAX_BUF_SIZE;
    93    byte in_buf[MAX_BUF_SIZE];
    94  
    95    string input;
    96    signing_instructions_message signing_message;
    97    if (!ReadFileIntoBlock(FLAGS_signing_instructions_file, &in_size,
    98                           in_buf)) {
    99      printf("Can't read signing instructions %s\n",
   100             FLAGS_signing_instructions_file.c_str());
   101      return 1;
   102    }
   103    input.assign((const char*)in_buf, in_size);
   104    if (!signing_message.ParseFromString(input)) {
   105      printf("Can't parse signing instructions\n");
   106      return 1;
   107    }
   108    printf("issuer: %s, duration: %ld, purpose: %s, hash: %s\n",
   109           signing_message.issuer().c_str(), (long)signing_message.duration(),
   110           signing_message.purpose().c_str(), signing_message.hash_alg().c_str());
   111  
   112    if (!signing_message.can_sign()) {
   113      printf("Signing is invalid\n");
   114      return 1;
   115    }
   116    printf("\nGot signing instructions\n");
   117  
   118    in_size = MAX_BUF_SIZE;
   119    private_key_blob_message private_key;
   120    if (!ReadFileIntoBlock(FLAGS_key_file, &in_size, in_buf)) {
   121      printf("Can't read private key\n");
   122      return 1;
   123    }
   124    input.assign((const char*)in_buf, in_size);
   125    if (!private_key.ParseFromString(input)) {
   126      printf("Can't parse private key\n");
   127      return 1;
   128    }
   129  
   130    printf("Key type: %s\n", private_key.key_type().c_str());
   131    printf("Key name: %s\n", private_key.key_name().c_str());
   132    string the_blob = private_key.blob();
   133    PrintBytes(the_blob.size(), (byte*)the_blob.data());
   134    const byte* p = (byte*)the_blob.data();
   135    RSA* signing_key = d2i_RSAPrivateKey(nullptr, &p, the_blob.size());
   136    if (signing_key == nullptr) {
   137      printf("Can't translate private key\n");
   138      return 1;
   139    }
   140    printf("\nGot signing key\n");
   141  
   142    // fill x509_cert_request_parameters_message
   143    x509_cert_request_parameters_message req_message;
   144    req_message.set_common_name(FLAGS_policy_identifier);
   145    req_message.mutable_key()->set_key_type("RSA");
   146    string* mod = BN_to_bin(*signing_key->n);
   147    if (mod == nullptr) {
   148      printf("Can't get private key modulus\n");
   149      return 1;
   150    }
   151    req_message.mutable_key()->mutable_rsa_key()->set_bit_modulus_size(
   152         BN_num_bits(signing_key->n));
   153    uint64_t expIn = 0x10001ULL;
   154    uint64_t expOut;
   155    ChangeEndian64((uint64_t*)&expIn, (uint64_t*)(&expOut));
   156  
   157    req_message.mutable_key()->mutable_rsa_key()->set_exponent(
   158        (const char*)&expOut, sizeof(uint64_t));
   159    req_message.mutable_key()->mutable_rsa_key()->set_modulus(
   160       mod->data(), mod->size());
   161    printf("\ncert request\n");
   162    print_cert_request_message(req_message); printf("\n\n");
   163    printf("\nGenerating request\n");
   164  
   165    X509_REQ* req = X509_REQ_new();
   166    X509_REQ_set_version(req, 2);
   167    // TODO(jlm): sign and verify request later
   168    if (!GenerateX509CertificateRequest(req_message, false, req)) {
   169      printf("Can't generate x509 request\n");
   170      return 1;
   171    }
   172    printf("Generated certificate request\n");
   173  
   174    // sign it
   175    X509* cert = X509_new();
   176    if (!SignX509Certificate(signing_key, true, signing_message, nullptr,
   177                             req, false, cert)) {
   178      printf("Can't sign x509 request\n");
   179      return 1;
   180    }
   181    printf("message signed\n");
   182  
   183    byte* out = nullptr;
   184    int size = i2d_X509(cert, &out);
   185    string output;
   186    output.assign((const char*)out, size);
   187    if (!WriteFileFromBlock(FLAGS_cert_file, output.size(),
   188                            (byte*)output.data())) {
   189      printf("Can't write cert\n");
   190      return 1;
   191    }
   192    return ret_val;
   193  }
   194