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