| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "entd/pkcs11.h" | 5 #include "entd/pkcs11.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <iostream> | 8 #include <iostream> |
| 9 #include <map> | 9 #include <map> |
| 10 #include <string> | 10 #include <string> |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 107 private: | 107 private: |
| 108 // The certificate may contain binary data, so store it as an array of bytes | 108 // The certificate may contain binary data, so store it as an array of bytes |
| 109 // instead of a string. | 109 // instead of a string. |
| 110 chromeos::Blob certificate_; | 110 chromeos::Blob certificate_; |
| 111 std::string subject_; | 111 std::string subject_; |
| 112 static Pkcs11CertificateHandler* certificate_handler_; | 112 static Pkcs11CertificateHandler* certificate_handler_; |
| 113 | 113 |
| 114 DISALLOW_COPY_AND_ASSIGN(Certificate); | 114 DISALLOW_COPY_AND_ASSIGN(Certificate); |
| 115 }; | 115 }; |
| 116 | 116 |
| 117 // class Pkcs11CertificateHandlerLocalFile | 117 // class Pkcs11TestCertificateHandler |
| 118 // Test Certificate handler that returns the contents of a file. | 118 // Test Certificate handler |
| 119 // | 119 class Pkcs11TestCertificateHandler : public Pkcs11CertificateHandler { |
| 120 // If the csr or cert file exists, the contents of the file is returned | |
| 121 // in BuildCSR or BuildCertificate; subject or content arguments are ignored. | |
| 122 // If the filename is empty or the file does not exist, a string | |
| 123 // containing the subject or content is returned instead. | |
| 124 class Pkcs11CertificateHandlerLocalFile : public Pkcs11CertificateHandler { | |
| 125 public: | 120 public: |
| 126 Pkcs11CertificateHandlerLocalFile(const std::string& csr, | 121 Pkcs11TestCertificateHandler() {} |
| 127 const std::string& cert) | 122 virtual ~Pkcs11TestCertificateHandler() {} |
| 128 : csr_filename_(csr), certificate_filename_(cert) { | |
| 129 if (!csr_filename_.empty()) | |
| 130 LOG(INFO) << "Using local CSR file: " << csr_filename_; | |
| 131 if (!certificate_filename_.empty()) | |
| 132 LOG(INFO) << "Using local Cert file: " << certificate_filename_; | |
| 133 } | |
| 134 virtual ~Pkcs11CertificateHandlerLocalFile() {} | |
| 135 virtual bool Initialize() { return true; } | 123 virtual bool Initialize() { return true; } |
| 136 | 124 |
| 137 virtual bool BuildCSR(const std::string& label, | 125 virtual bool BuildCSR(const std::string& label, |
| 138 const std::string& subject, | 126 const std::string& subject, |
| 139 std::string* csr) { | 127 std::string* csr) { |
| 140 if (!csr_filename_.empty()) | 128 // Use the subject as the CSR string. |
| 141 file_util::ReadFileToString(FilePath(csr_filename_), csr); | 129 *csr = subject; |
| 142 if (csr->empty()) { | |
| 143 // Default CSR string if not read from a file | |
| 144 *csr = std::string("<CSR subject=") + subject + " />"; | |
| 145 } | |
| 146 return true; | 130 return true; |
| 147 } | 131 } |
| 148 | 132 |
| 149 virtual bool BuildCertificate(const std::string& content, | 133 virtual bool BuildCertificate(const std::string& content, |
| 150 chromeos::Blob* certificate, | 134 chromeos::Blob* certificate, |
| 151 std::string* subject) { | 135 std::string* subject) { |
| 152 std::string subjectstr; | 136 // Use the unmodified content for the certificate. |
| 137 certificate->resize(content.length()); |
| 138 memcpy(&(certificate->front()), content.c_str(), content.length()); |
| 139 *subject = "Test"; |
| 153 | 140 |
| 154 if (!certificate_filename_.empty()) { | |
| 155 // Try reading the certificate from the filename set at construction. | |
| 156 FilePath filepath(certificate_filename_); | |
| 157 int64 filesize; | |
| 158 bool file_read = file_util::GetFileSize(filepath, &filesize); | |
| 159 if (file_read) { | |
| 160 certificate->resize(filesize); | |
| 161 char* dest = reinterpret_cast<char*>(&(certificate->front())); | |
| 162 int res = file_util::ReadFile(filepath, dest, filesize); | |
| 163 if (res == filesize) { | |
| 164 *subject = std::string("File: ") + certificate_filename_; | |
| 165 } else { | |
| 166 file_read = false; | |
| 167 } | |
| 168 } | |
| 169 if (!file_read) { | |
| 170 LOG(ERROR) << "Error reading file: " << filepath.value(); | |
| 171 return false; | |
| 172 } | |
| 173 } else { | |
| 174 // Use a test string for debugging. | |
| 175 std::string certstr = | |
| 176 std::string("<Certificate content=") + content + " />"; | |
| 177 certificate->resize(certstr.length()); | |
| 178 memcpy(&(certificate->front()), certstr.c_str(), certstr.length()); | |
| 179 *subject = "Content"; | |
| 180 } | |
| 181 return true; | 141 return true; |
| 182 } | 142 } |
| 183 | 143 |
| 184 private: | 144 private: |
| 185 std::string csr_filename_; | 145 DISALLOW_COPY_AND_ASSIGN(Pkcs11TestCertificateHandler); |
| 186 std::string certificate_filename_; | |
| 187 }; | |
| 188 | |
| 189 // Class Pkcs11CertificateHandlerOpenSsl | |
| 190 // Implements CSR generation using 'system("openssl req...")'. | |
| 191 class Pkcs11CertificateHandlerOpenSsl : public Pkcs11CertificateHandler { | |
| 192 public: | |
| 193 Pkcs11CertificateHandlerOpenSsl() : use_DER_format_(false) {} | |
| 194 | |
| 195 virtual ~Pkcs11CertificateHandlerOpenSsl() {} | |
| 196 | |
| 197 virtual bool Initialize() { return true; } | |
| 198 | |
| 199 // If called, openssl will be told to convert the certificate to DER format. | |
| 200 // DER is the format that opencryptoki expects. | |
| 201 void SetOutputDER() { use_DER_format_ = true; } | |
| 202 | |
| 203 virtual bool BuildCSR(const std::string& label, | |
| 204 const std::string& subject, | |
| 205 std::string* csr) { | |
| 206 // temporary filenames | |
| 207 FilePath temp_dir; | |
| 208 file_util::GetTempDir(&temp_dir); | |
| 209 FilePath private_key_fp = temp_dir.Append("privkey"); | |
| 210 FilePath csr_fp = temp_dir.Append("csr"); | |
| 211 | |
| 212 // Get the passphrase for the private key from the slot handler | |
| 213 std::string passphrase = slot_handler()->GetPassphrase(label); | |
| 214 | |
| 215 // *TODO: replace with calls to libopenssl to avoid system() call. | |
| 216 if (!CheckString(subject) || | |
| 217 !CheckString(passphrase)) { | |
| 218 return false; | |
| 219 } | |
| 220 std::string cmd = | |
| 221 std::string("openssl req -new -batch -newkey rsa:2048") | |
| 222 + " -keyout " + private_key_fp.value() | |
| 223 + " -subj \"" + subject + "\"" | |
| 224 + " -pubkey -out " + csr_fp.value(); | |
| 225 if (!passphrase.empty()) | |
| 226 cmd += " -passout pass:" + passphrase; | |
| 227 else | |
| 228 cmd += " -nodes"; | |
| 229 CallSystem(cmd); | |
| 230 | |
| 231 // get the results from the temporary files | |
| 232 std::string csr_output; | |
| 233 if (file_util::ReadFileToString(csr_fp, &csr_output)) { | |
| 234 csr_ = GetCertSection(csr_output, | |
| 235 "-----BEGIN CERTIFICATE REQUEST-----", | |
| 236 "-----END CERTIFICATE REQUEST-----"); | |
| 237 public_key_ = GetCertSection(csr_output, | |
| 238 "-----BEGIN PUBLIC KEY-----", | |
| 239 "-----END PUBLIC KEY-----"); | |
| 240 } | |
| 241 file_util::ReadFileToString(private_key_fp, &private_key_); | |
| 242 | |
| 243 // remove temporary files | |
| 244 file_util::Delete(private_key_fp, false); | |
| 245 file_util::Delete(csr_fp, false); | |
| 246 | |
| 247 // Convert the pivate key to DER format and pass it to the slot handler. | |
| 248 if (use_DER_format_ && !private_key_.empty()) { | |
| 249 chromeos::Blob key_der; | |
| 250 if (!ConvertToDER(private_key_, passphrase, &key_der)) | |
| 251 return false; | |
| 252 if (!slot_handler()->AddPrivateKey(label, subject, key_der)) | |
| 253 return false; | |
| 254 } | |
| 255 | |
| 256 *csr = csr_; | |
| 257 | |
| 258 return true; | |
| 259 } | |
| 260 | |
| 261 // Include the private key (encoded with the SlotObject's passphrase) | |
| 262 // with the certificate so that it can be decoded with the passphrase. | |
| 263 virtual bool BuildCertificate(const std::string& content, | |
| 264 chromeos::Blob* certificate, | |
| 265 std::string* subject) { | |
| 266 FilePath temp_dir; | |
| 267 file_util::GetTempDir(&temp_dir); | |
| 268 FilePath cert_pem_fp = temp_dir.Append("cert.pem"); | |
| 269 FilePath cert_der_fp = temp_dir.Append("cert.der"); | |
| 270 FilePath subject_fp = temp_dir.Append("subject"); | |
| 271 | |
| 272 if (content.empty()) { | |
| 273 LOG(ERROR) << "BuildCertificate called with empty content"; | |
| 274 return false; | |
| 275 } | |
| 276 | |
| 277 // Write the content string to a temporary file | |
| 278 // to use as the certificate contents. | |
| 279 int res = file_util::WriteFile( | |
| 280 cert_pem_fp, content.c_str(), content.length()); | |
| 281 if (res < 0) { | |
| 282 LOG(ERROR) << "Unable to write temporary file: " << cert_pem_fp.value(); | |
| 283 return false; | |
| 284 } | |
| 285 | |
| 286 { | |
| 287 // Use openssl to write the subject and (if needed) | |
| 288 // the DER version of the certificate | |
| 289 // *TODO: replace with calls to libopenssl to avoid system() call. | |
| 290 std::string cmd("openssl x509"); | |
| 291 cmd += " -inform PEM -in " + cert_pem_fp.value(); | |
| 292 if (use_DER_format_) | |
| 293 cmd += " -outform DER -out " + cert_der_fp.value(); | |
| 294 else | |
| 295 cmd += " -noout"; | |
| 296 cmd += " -subject > " + subject_fp.value(); | |
| 297 bool res = CallSystem(cmd); | |
| 298 | |
| 299 file_util::Delete(cert_pem_fp, false); | |
| 300 if (!res) { | |
| 301 file_util::Delete(cert_der_fp, false); | |
| 302 file_util::Delete(subject_fp, false); | |
| 303 return false; | |
| 304 } | |
| 305 } | |
| 306 | |
| 307 if (use_DER_format_) { | |
| 308 // read in the DER version of the certificate. | |
| 309 int64 certlen; | |
| 310 int res = -1; | |
| 311 if (file_util::GetFileSize(cert_der_fp, &certlen)) { | |
| 312 certificate->resize(certlen); | |
| 313 char* dest = reinterpret_cast<char*>(&(certificate->front())); | |
| 314 res = file_util::ReadFile(cert_der_fp, dest, certlen); | |
| 315 } | |
| 316 file_util::Delete(cert_der_fp, false); | |
| 317 if (res != certlen) { | |
| 318 LOG(ERROR) << "Unable to read DER file: " << cert_der_fp.value(); | |
| 319 file_util::Delete(subject_fp, false); | |
| 320 certificate->clear(); | |
| 321 return false; | |
| 322 } | |
| 323 } else { | |
| 324 std::string certstr; | |
| 325 if (!content.empty()) { | |
| 326 // Include content provided by script. | |
| 327 certstr = content; | |
| 328 } else { | |
| 329 // Include the (test) certificate file. | |
| 330 int64 certlen; | |
| 331 int res = -1; | |
| 332 if (file_util::GetFileSize(cert_pem_fp, &certlen)) { | |
| 333 const int cert_max_length = 256*1024; | |
| 334 if (certlen < cert_max_length) { | |
| 335 char* certvec = new char[certlen]; | |
| 336 res = file_util::ReadFile(cert_pem_fp, &certvec[0], certlen); | |
| 337 if (res == certlen) { | |
| 338 certstr = std::string(certvec, certlen); | |
| 339 } | |
| 340 } | |
| 341 } | |
| 342 } | |
| 343 // Append the private key. | |
| 344 certstr += private_key_; | |
| 345 // Copy to certificate. | |
| 346 certificate->resize(certstr.length()); | |
| 347 memcpy(&(certificate->front()), certstr.c_str(), certstr.length()); | |
| 348 } | |
| 349 | |
| 350 { | |
| 351 // read in the subject | |
| 352 int64 subjectlen; | |
| 353 int res = -1; | |
| 354 if (file_util::GetFileSize(subject_fp, &subjectlen)) { | |
| 355 const int subject_max_length = 4096; | |
| 356 if (subjectlen < subject_max_length) { | |
| 357 char* subjectvec = new char[subjectlen]; | |
| 358 res = file_util::ReadFile(subject_fp, &subjectvec[0], subjectlen); | |
| 359 if (res == subjectlen) { | |
| 360 const std::string headerstr("subject= "); | |
| 361 std::string subjstr(subjectvec, subjectlen); | |
| 362 std::string::size_type idx = subjstr.find(headerstr); | |
| 363 if (idx != std::string::npos) | |
| 364 subject->assign(subjstr.substr(idx + headerstr.length())); | |
| 365 else | |
| 366 subject->assign(subjstr); | |
| 367 } | |
| 368 } | |
| 369 } | |
| 370 file_util::Delete(subject_fp, false); | |
| 371 if (res != subjectlen) { | |
| 372 LOG(ERROR) << "Unable to read subject file: " << subject_fp.value(); | |
| 373 return false; | |
| 374 } | |
| 375 } | |
| 376 | |
| 377 return true; | |
| 378 } | |
| 379 | |
| 380 protected: | |
| 381 bool ConvertToDER(const std::string& key, | |
| 382 const std::string& passphrase, | |
| 383 chromeos::Blob* key_der) { | |
| 384 FilePath temp_dir; | |
| 385 file_util::GetTempDir(&temp_dir); | |
| 386 FilePath key_pem_fp = temp_dir.Append("key.pem"); | |
| 387 FilePath key_der_fp = temp_dir.Append("key.der"); | |
| 388 | |
| 389 // Write the key to a temporary file | |
| 390 int res = file_util::WriteFile(key_pem_fp, key.c_str(), key.length()); | |
| 391 if (res < 0) { | |
| 392 LOG(ERROR) << "Unable to write temporary file: " << key_pem_fp.value(); | |
| 393 return false; | |
| 394 } | |
| 395 | |
| 396 // Use openssl to write the the DER version of the key | |
| 397 // *TODO: replace with calls to libopenssl to avoid system() call. | |
| 398 if (!CheckString(passphrase)) { | |
| 399 return false; | |
| 400 } | |
| 401 std::string cmd = std::string("openssl rsa") | |
| 402 + " -inform PEM -in " + key_pem_fp.value() | |
| 403 + " -outform DER -out " + key_der_fp.value(); | |
| 404 if (!passphrase.empty()) | |
| 405 cmd += " -passin pass:" + passphrase; | |
| 406 CallSystem(cmd); | |
| 407 | |
| 408 // read in the DER version of the key. | |
| 409 int64 keylen; | |
| 410 res = -1; | |
| 411 if (file_util::GetFileSize(key_der_fp, &keylen)) { | |
| 412 key_der->resize(keylen); | |
| 413 char* dest = reinterpret_cast<char*>(&(key_der->front())); | |
| 414 res = file_util::ReadFile(key_der_fp, dest, keylen); | |
| 415 } | |
| 416 | |
| 417 file_util::Delete(key_pem_fp, false); | |
| 418 file_util::Delete(key_der_fp, false); | |
| 419 | |
| 420 if (res != keylen) { | |
| 421 LOG(ERROR) << "Unable to read key DER file: " << key_der_fp.value(); | |
| 422 return false; | |
| 423 } | |
| 424 return true; | |
| 425 } | |
| 426 | |
| 427 // Return the substring of 's' | |
| 428 // starting with 'begin' and ending with 'end' (inclusive) | |
| 429 std::string GetCertSection(const std::string& s, | |
| 430 const std::string& begin, | |
| 431 const std::string& end) { | |
| 432 std::string::size_type idx0 = s.find(begin); | |
| 433 std::string::size_type idx1 = s.find(end); | |
| 434 if (idx0 == std::string::npos || idx1 == std::string::npos) { | |
| 435 LOG(WARNING) << "Unable to find section: [" | |
| 436 << begin << ", " << end << "]"; | |
| 437 LOG(WARNING) << "In:\n" << s; | |
| 438 return std::string(); | |
| 439 } | |
| 440 return s.substr(idx0, (idx1 + end.length()) - idx0); | |
| 441 } | |
| 442 | |
| 443 bool CheckString(const std::string& instr) { | |
| 444 for (std::string::const_iterator iter = instr.begin(); | |
| 445 iter != instr.end(); ++iter) { | |
| 446 char c = *iter; | |
| 447 if (c == '"') { | |
| 448 LOG(ERROR) << "Invalid string: " << instr; | |
| 449 return false; | |
| 450 } | |
| 451 } | |
| 452 return true; | |
| 453 } | |
| 454 | |
| 455 bool CallSystem(const std::string& cmd) { | |
| 456 LOG(INFO) << "Calling system(" << cmd << ");"; | |
| 457 int res = system(cmd.c_str()); | |
| 458 if (res != 0) { | |
| 459 LOG(WARNING) << "Error executing command: '" << cmd << "'\n" | |
| 460 << " result = " << res; | |
| 461 return false; | |
| 462 } | |
| 463 return true; | |
| 464 } | |
| 465 | |
| 466 bool use_DER_format_; | |
| 467 | |
| 468 std::string csr_; | |
| 469 std::string certificate_; | |
| 470 std::string private_key_; | |
| 471 std::string public_key_; | |
| 472 }; | |
| 473 | |
| 474 // In this implementation, instead of generating a public/private key pair, | |
| 475 // use engine_pkcs11 to get the keys from the TPM. | |
| 476 class Pkcs11CertificateHandlerOpenSslPkcs11Engine : | |
| 477 public Pkcs11CertificateHandlerOpenSsl { | |
| 478 | |
| 479 public: | |
| 480 void SetEngineConfigFile(const std::string& filename) { | |
| 481 engine_config_file_ = filename; | |
| 482 } | |
| 483 | |
| 484 virtual bool BuildCSR(const std::string& label, | |
| 485 const std::string& subject, | |
| 486 std::string* csr) { | |
| 487 FilePath temp_dir; | |
| 488 file_util::GetTempDir(&temp_dir); | |
| 489 FilePath csr_fp = temp_dir.Append("csr"); | |
| 490 | |
| 491 csr_.clear(); | |
| 492 | |
| 493 if (engine_config_file_.empty()) { | |
| 494 LOG(ERROR) << "BuildCSR called with no engine config file specified."; | |
| 495 return false; | |
| 496 } | |
| 497 | |
| 498 // *TODO: replace with calls to libopenssl to avoid system() call. | |
| 499 std::string keyid = slot_handler()->GetKeyIdentifier(label); | |
| 500 std::stringstream cmd; | |
| 501 if (!CheckString(subject)) { | |
| 502 return false; | |
| 503 } | |
| 504 cmd << "openssl req -new -batch" | |
| 505 << " -config " << engine_config_file_ << " -engine pkcs11" | |
| 506 << " -key " << keyid << " -keyform engine" | |
| 507 << " -subj \"" << subject << "\"" | |
| 508 << " -out " << csr_fp.value(); | |
| 509 CallSystem(cmd.str()); | |
| 510 | |
| 511 bool res = file_util::ReadFileToString(csr_fp, &csr_); | |
| 512 if (!res) { | |
| 513 LOG(ERROR) << "Unable to read CSR file: " << csr_fp.value(); | |
| 514 return false; | |
| 515 } | |
| 516 | |
| 517 // remove temporary files | |
| 518 file_util::Delete(csr_fp, false); | |
| 519 | |
| 520 *csr = csr_; | |
| 521 | |
| 522 return true; | |
| 523 } | |
| 524 | |
| 525 // BuildCertificate() is the same as in the parent class, | |
| 526 // but note that private_key_ will be empty, so nothing will be | |
| 527 // appended to the certificate contents (as desired). | |
| 528 | |
| 529 private: | |
| 530 std::string engine_config_file_; | |
| 531 }; | 146 }; |
| 532 | 147 |
| 533 // Class Pkcs11CertificateHandlerLibOpenSsl | 148 // Class Pkcs11CertificateHandlerLibOpenSsl |
| 534 // Implements CSR generation using the openssl crypto library | 149 // Implements CSR generation using the openssl crypto library |
| 535 class Pkcs11CertificateHandlerLibOpenSsl : public Pkcs11CertificateHandler { | 150 class Pkcs11CertificateHandlerLibOpenSsl : public Pkcs11CertificateHandler { |
| 536 public: | 151 public: |
| 537 Pkcs11CertificateHandlerLibOpenSsl() {} | 152 Pkcs11CertificateHandlerLibOpenSsl() {} |
| 538 | 153 |
| 539 virtual ~Pkcs11CertificateHandlerLibOpenSsl() {} | 154 virtual ~Pkcs11CertificateHandlerLibOpenSsl() {} |
| 540 | 155 |
| (...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 888 } | 503 } |
| 889 | 504 |
| 890 static const long kRsaKeyLength; | 505 static const long kRsaKeyLength; |
| 891 static const long kRsaKeyExponent; | 506 static const long kRsaKeyExponent; |
| 892 static const long kMaxFilePath; | 507 static const long kMaxFilePath; |
| 893 | 508 |
| 894 std::string csr_; | 509 std::string csr_; |
| 895 std::string certificate_; | 510 std::string certificate_; |
| 896 std::string public_key_; | 511 std::string public_key_; |
| 897 chromeos::Blob private_key_der_; | 512 chromeos::Blob private_key_der_; |
| 513 |
| 514 DISALLOW_COPY_AND_ASSIGN(Pkcs11CertificateHandlerLibOpenSsl); |
| 898 }; | 515 }; |
| 899 | 516 |
| 900 // Use 2048 bits for the key length, and an exponent of 0x10001. | 517 // Use 2048 bits for the key length, and an exponent of 0x10001. |
| 901 const long Pkcs11CertificateHandlerLibOpenSsl::kRsaKeyLength = 2048; | 518 const long Pkcs11CertificateHandlerLibOpenSsl::kRsaKeyLength = 2048; |
| 902 const long Pkcs11CertificateHandlerLibOpenSsl::kRsaKeyExponent = 0x10001; | 519 const long Pkcs11CertificateHandlerLibOpenSsl::kRsaKeyExponent = 0x10001; |
| 903 // Max number of chars for local array allocation for file paths. | 520 // Max number of chars for local array allocation for file paths. |
| 904 const long Pkcs11CertificateHandlerLibOpenSsl::kMaxFilePath = 1024; | 521 const long Pkcs11CertificateHandlerLibOpenSsl::kMaxFilePath = 1024; |
| 905 | 522 |
| 906 | 523 |
| 907 // Class Pkcs11SlotHandlerInMemory | 524 // Class Pkcs11SlotHandlerInMemory |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1059 ObjectMap::iterator iter = objects_.find(label); | 676 ObjectMap::iterator iter = objects_.find(label); |
| 1060 if (iter == objects_.end()) { | 677 if (iter == objects_.end()) { |
| 1061 return false; | 678 return false; |
| 1062 } else { | 679 } else { |
| 1063 objects_.erase(iter); // Will delete Object | 680 objects_.erase(iter); // Will delete Object |
| 1064 return true; | 681 return true; |
| 1065 } | 682 } |
| 1066 } | 683 } |
| 1067 | 684 |
| 1068 ObjectMap objects_; | 685 ObjectMap objects_; |
| 686 |
| 1069 DISALLOW_COPY_AND_ASSIGN(Pkcs11SlotHandlerInMemory); | 687 DISALLOW_COPY_AND_ASSIGN(Pkcs11SlotHandlerInMemory); |
| 1070 }; | 688 }; |
| 1071 | 689 |
| 1072 | 690 |
| 1073 // Class Pkcs11SlotHandlerOpenCryptoki | 691 // Class Pkcs11SlotHandlerOpenCryptoki |
| 1074 // Inherits from Pkcs11SlotHandlerInMemory to share memory mapping of objects | 692 // Inherits from Pkcs11SlotHandlerInMemory to share memory mapping of objects |
| 1075 class Pkcs11SlotHandlerOpenCryptoki : public Pkcs11SlotHandlerInMemory { | 693 class Pkcs11SlotHandlerOpenCryptoki : public Pkcs11SlotHandlerInMemory { |
| 1076 public: | 694 public: |
| 1077 Pkcs11SlotHandlerOpenCryptoki() | 695 Pkcs11SlotHandlerOpenCryptoki() |
| 1078 : user_pin_(""), slot_index_(0), slot_id_(0) { } | 696 : user_pin_(""), slot_index_(0), slot_id_(0) { } |
| (...skipping 681 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1760 return chromeos::AsciiEncode(bytes); | 1378 return chromeos::AsciiEncode(bytes); |
| 1761 } | 1379 } |
| 1762 | 1380 |
| 1763 std::string user_pin_; | 1381 std::string user_pin_; |
| 1764 CK_ULONG slot_index_; | 1382 CK_ULONG slot_index_; |
| 1765 CK_SLOT_ID slot_id_; | 1383 CK_SLOT_ID slot_id_; |
| 1766 | 1384 |
| 1767 DISALLOW_COPY_AND_ASSIGN(Pkcs11SlotHandlerOpenCryptoki); | 1385 DISALLOW_COPY_AND_ASSIGN(Pkcs11SlotHandlerOpenCryptoki); |
| 1768 }; | 1386 }; |
| 1769 | 1387 |
| 1770 // In "GLaptop mode" we generate the key pair using openssl, and call | 1388 // Pkcs11CertificateHandlerLibOpenSsl generates its own key pair, |
| 1771 // AddPrivateKey() instead, so GenerateKeyPair() needs to be a no-op. | 1389 // which is what we would prefer to use. However, engine_pkcs11 |
| 1772 class Pkcs11SlotHandlerGLaptop : public Pkcs11SlotHandlerOpenCryptoki { | 1390 // is not currently working correctly, and there is no known |
| 1391 // implementation that can generate a CSR using the TPM generated key pair. |
| 1392 // (The current implementaiton of Pkcs11CertificateHandlerLibOpenSsl calls |
| 1393 // AddPrivateKey() instead). |
| 1394 // Rather than eliminate the poentially useful (and non-trivial) code in |
| 1395 // Pkcs11SlotHandlerOpenCryptoki, override the class with a GenerateKeyPair() |
| 1396 // method that just sets the passphrase and ensures that the object exists. |
| 1397 class Pkcs11SlotHandlerOpenCryptokiNoKeyGen : |
| 1398 public Pkcs11SlotHandlerOpenCryptoki { |
| 1773 public: | 1399 public: |
| 1774 Pkcs11SlotHandlerGLaptop() {} | 1400 Pkcs11SlotHandlerOpenCryptokiNoKeyGen() {} |
| 1775 | 1401 |
| 1402 // Don't actually generate a key pair; rely on AddPrivateKey() getting |
| 1403 // called instead. |
| 1776 virtual bool GenerateKeyPair(const std::string& label, | 1404 virtual bool GenerateKeyPair(const std::string& label, |
| 1777 const std::string& passphrase) { | 1405 const std::string& passphrase) { |
| 1778 Object* obj = GetObject(label); | 1406 Object* obj = GetObject(label); |
| 1779 if (!obj) { | 1407 if (!obj) { |
| 1780 LOG(WARNING) << "BuildSlotObject must be called before GenerateKeyPair"; | 1408 LOG(WARNING) << "BuildSlotObject must be called before GenerateKeyPair"; |
| 1781 return false; | 1409 return false; |
| 1782 } | 1410 } |
| 1783 obj->passphrase_ = passphrase; | 1411 obj->passphrase_ = passphrase; |
| 1784 return true; | 1412 return true; |
| 1785 }; | 1413 }; |
| 1786 | 1414 |
| 1787 private: | 1415 private: |
| 1788 DISALLOW_COPY_AND_ASSIGN(Pkcs11SlotHandlerGLaptop); | 1416 DISALLOW_COPY_AND_ASSIGN(Pkcs11SlotHandlerOpenCryptokiNoKeyGen); |
| 1789 }; | 1417 }; |
| 1790 | 1418 |
| 1791 // Class CSR | 1419 // Class CSR |
| 1792 // CSR JavaScript interface wrapper around Pkcs11CertificateHandler. | 1420 // CSR JavaScript interface wrapper around Pkcs11CertificateHandler. |
| 1793 class CSR : public JSObjectWrapper<CSR> { | 1421 class CSR : public JSObjectWrapper<CSR> { |
| 1794 public: | 1422 public: |
| 1795 CSR() { } | 1423 CSR() { } |
| 1796 virtual ~CSR() {} | 1424 virtual ~CSR() {} |
| 1797 | 1425 |
| 1798 // JSObjectWrapper Interface | 1426 // JSObjectWrapper Interface |
| (...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2074 // Called any time slot_handler_ or certificate_handler_ gets set. | 1702 // Called any time slot_handler_ or certificate_handler_ gets set. |
| 2075 void Pkcs11::SetupHandlers() { | 1703 void Pkcs11::SetupHandlers() { |
| 2076 // The certificate handler may need access to the slot handler | 1704 // The certificate handler may need access to the slot handler |
| 2077 certificate_handler()->SetSlotHandler(slot_handler()); | 1705 certificate_handler()->SetSlotHandler(slot_handler()); |
| 2078 | 1706 |
| 2079 // Set up the CSR and Certificate sub-classes with the certificate handler. | 1707 // Set up the CSR and Certificate sub-classes with the certificate handler. |
| 2080 CSR::InitCertificateHandler(certificate_handler()); | 1708 CSR::InitCertificateHandler(certificate_handler()); |
| 2081 Certificate::InitCertificateHandler(certificate_handler()); | 1709 Certificate::InitCertificateHandler(certificate_handler()); |
| 2082 } | 1710 } |
| 2083 | 1711 |
| 2084 // This always gets called first by InitializeXXX() | |
| 2085 // so that obj() is available for other initialization | |
| 2086 // functions (e.g. ReadObjectsFromSlot()) | |
| 2087 bool Pkcs11::Initialize() { | 1712 bool Pkcs11::Initialize() { |
| 2088 if (slot_handler_.get() == NULL) { | 1713 // Initialize the SlotObject template here so that we can embed 'this'. |
| 2089 // Default slot handler | |
| 2090 slot_handler_.reset(new Pkcs11SlotHandlerInMemory()); | |
| 2091 if (!slot_handler_->Initialize()) | |
| 2092 return false; | |
| 2093 } | |
| 2094 if (certificate_handler_.get() == NULL) { | |
| 2095 // Default certificate handler. | |
| 2096 certificate_handler_.reset(new Pkcs11CertificateHandlerLocalFile("", "")); | |
| 2097 if (!certificate_handler_->Initialize()) | |
| 2098 return false; | |
| 2099 } | |
| 2100 | |
| 2101 SetupHandlers(); | |
| 2102 | |
| 2103 // Initialize the pkcs11 template specially | |
| 2104 v8::Handle<v8::FunctionTemplate> t = GetTemplate(); | 1714 v8::Handle<v8::FunctionTemplate> t = GetTemplate(); |
| 2105 v8::Handle<v8::ObjectTemplate> t_obj = t->InstanceTemplate(); | 1715 v8::Handle<v8::ObjectTemplate> t_obj = t->InstanceTemplate(); |
| 2106 t_obj->Set(v8::String::NewSymbol("SlotObject"), | 1716 t_obj->Set(v8::String::NewSymbol("SlotObject"), |
| 2107 v8::FunctionTemplate::New(SlotObject::Construct, | 1717 v8::FunctionTemplate::New(SlotObject::Construct, |
| 2108 v8::External::Wrap(this)), | 1718 v8::External::Wrap(this)), |
| 2109 v8::ReadOnly); | 1719 v8::ReadOnly); |
| 2110 | 1720 |
| 2111 // Build and initialize the V8 object. | 1721 // Build and initialize the V8 object. |
| 2112 return JSObjectWrapper<Pkcs11>::Initialize(); | 1722 if (!JSObjectWrapper<Pkcs11>::Initialize()) |
| 1723 return false; |
| 1724 |
| 1725 // Default handlers |
| 1726 if (certificate_handler_.get() == NULL) { |
| 1727 certificate_handler_.reset(new Pkcs11TestCertificateHandler()); |
| 1728 if (!certificate_handler_->Initialize()) |
| 1729 return false; |
| 1730 } |
| 1731 if (slot_handler_.get() == NULL) { |
| 1732 slot_handler_.reset(new Pkcs11SlotHandlerInMemory()); |
| 1733 if (!slot_handler_->Initialize()) |
| 1734 return false; |
| 1735 } |
| 1736 SetupHandlers(); |
| 1737 |
| 1738 return true; |
| 2113 } | 1739 } |
| 2114 | 1740 |
| 2115 bool Pkcs11::InitializeOpenCryptoki(const std::string& engine) { | 1741 // Used for testing the OpenSSL functionality without requiring |
| 2116 LOG(INFO) << "Initializing pkcs11 with opencryptoki and engine:" << engine; | 1742 // opencryptoki to be configured in the OS. |
| 2117 | 1743 bool Pkcs11::SetOpenSSLHandlers() { |
| 2118 if (!Initialize()) | |
| 2119 return false; | |
| 2120 | |
| 2121 Pkcs11SlotHandlerOpenCryptoki* slot_handler = | |
| 2122 new Pkcs11SlotHandlerOpenCryptoki(); | |
| 2123 slot_handler_.reset(slot_handler); | |
| 2124 if (!slot_handler->Initialize()) | |
| 2125 return false; | |
| 2126 slot_handler->ReadObjectsFromSlot(this); | |
| 2127 | |
| 2128 Pkcs11CertificateHandlerOpenSslPkcs11Engine* cert_handler = | |
| 2129 new Pkcs11CertificateHandlerOpenSslPkcs11Engine(); | |
| 2130 if (!cert_handler->Initialize()) | |
| 2131 return false; | |
| 2132 cert_handler->SetEngineConfigFile(engine); | |
| 2133 cert_handler->SetOutputDER(); | |
| 2134 certificate_handler_.reset(cert_handler); | |
| 2135 | |
| 2136 SetupHandlers(); | |
| 2137 | |
| 2138 return true;; | |
| 2139 } | |
| 2140 | |
| 2141 bool Pkcs11::InitializeGLaptop() { | |
| 2142 LOG(INFO) << "Initializing pkcs11 with opencryptoki and openssl:libcrypto."; | |
| 2143 | |
| 2144 if (!Initialize()) | |
| 2145 return false; | |
| 2146 | |
| 2147 Pkcs11SlotHandlerGLaptop* slot_handler = | |
| 2148 new Pkcs11SlotHandlerGLaptop(); | |
| 2149 slot_handler_.reset(slot_handler); | |
| 2150 if (!slot_handler->Initialize()) | |
| 2151 return false; | |
| 2152 slot_handler->ReadObjectsFromSlot(this); | |
| 2153 | |
| 2154 Pkcs11CertificateHandlerLibOpenSsl* cert_handler = | 1744 Pkcs11CertificateHandlerLibOpenSsl* cert_handler = |
| 2155 new Pkcs11CertificateHandlerLibOpenSsl(); | 1745 new Pkcs11CertificateHandlerLibOpenSsl(); |
| 2156 if (!cert_handler->Initialize()) | 1746 if (!cert_handler->Initialize()) |
| 2157 return false; | 1747 return false; |
| 2158 certificate_handler_.reset(cert_handler); | 1748 certificate_handler_.reset(cert_handler); |
| 2159 | 1749 |
| 2160 SetupHandlers(); | 1750 SetupHandlers(); |
| 2161 | 1751 |
| 2162 return true; | 1752 return true; |
| 2163 } | 1753 } |
| 2164 | 1754 |
| 2165 bool Pkcs11::InitializeOpenSSL() { | 1755 // Requires opencryptoki to be configured properly in the OS, |
| 2166 LOG(INFO) << "Initializing pkcs11 with openssl."; | 1756 // otherwise C_Initialize() will fail. |
| 2167 | 1757 bool Pkcs11::SetOpenCryptokiHandlers() { |
| 2168 if (!Initialize()) | 1758 Pkcs11CertificateHandlerLibOpenSsl* cert_handler = |
| 2169 return false; | 1759 new Pkcs11CertificateHandlerLibOpenSsl(); |
| 2170 | |
| 2171 slot_handler_.reset(new Pkcs11SlotHandlerInMemory()); | |
| 2172 if (!slot_handler_->Initialize()) | |
| 2173 return false; | |
| 2174 | |
| 2175 Pkcs11CertificateHandlerOpenSsl* cert_handler = | |
| 2176 new Pkcs11CertificateHandlerOpenSsl(); | |
| 2177 if (!cert_handler->Initialize()) | 1760 if (!cert_handler->Initialize()) |
| 2178 return false; | 1761 return false; |
| 2179 certificate_handler_.reset(cert_handler); | 1762 certificate_handler_.reset(cert_handler); |
| 2180 | 1763 |
| 2181 SetupHandlers(); | 1764 Pkcs11SlotHandlerOpenCryptokiNoKeyGen* slot_handler = |
| 2182 | 1765 new Pkcs11SlotHandlerOpenCryptokiNoKeyGen(); |
| 2183 return true; | 1766 slot_handler_.reset(slot_handler); |
| 2184 } | 1767 if (!slot_handler->Initialize()) |
| 2185 | |
| 2186 bool Pkcs11::InitializeLocalFiles(const std::string& csr, | |
| 2187 const std::string& cert) { | |
| 2188 if (!Initialize()) | |
| 2189 return false; | 1768 return false; |
| 2190 | 1769 slot_handler->ReadObjectsFromSlot(this); |
| 2191 slot_handler_.reset(new Pkcs11SlotHandlerInMemory()); | |
| 2192 if (!slot_handler_->Initialize()) | |
| 2193 return false; | |
| 2194 | |
| 2195 certificate_handler_.reset( | |
| 2196 new Pkcs11CertificateHandlerLocalFile(csr, cert)); | |
| 2197 if (!certificate_handler_->Initialize()) | |
| 2198 return false; | |
| 2199 | 1770 |
| 2200 SetupHandlers(); | 1771 SetupHandlers(); |
| 2201 | 1772 |
| 2202 return true; | 1773 return true; |
| 2203 } | 1774 } |
| 2204 | 1775 |
| 2205 // pkcs11[slot_object->label()] = slot_object->obj() | 1776 // pkcs11[slot_object->label()] = slot_object->obj() |
| 2206 bool Pkcs11::AddJSSlotObject(const SlotObject* slot_object) { | 1777 bool Pkcs11::AddJSSlotObject(const SlotObject* slot_object) { |
| 2207 v8::Local<v8::Value> slotsvalue = obj()->Get(v8::String::NewSymbol("slots")); | 1778 v8::Local<v8::Value> slotsvalue = obj()->Get(v8::String::NewSymbol("slots")); |
| 2208 if (slotsvalue.IsEmpty() || !slotsvalue->IsObject()) { | 1779 if (slotsvalue.IsEmpty() || !slotsvalue->IsObject()) { |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2290 v8::ReadOnly); | 1861 v8::ReadOnly); |
| 2291 template_object->Set(v8::String::NewSymbol("remove"), | 1862 template_object->Set(v8::String::NewSymbol("remove"), |
| 2292 v8::FunctionTemplate::New(dispatch_removeSlotObject), | 1863 v8::FunctionTemplate::New(dispatch_removeSlotObject), |
| 2293 v8::ReadOnly); | 1864 v8::ReadOnly); |
| 2294 template_object->Set(v8::String::NewSymbol("slots"), | 1865 template_object->Set(v8::String::NewSymbol("slots"), |
| 2295 v8::Object::New(), | 1866 v8::Object::New(), |
| 2296 v8::ReadOnly); | 1867 v8::ReadOnly); |
| 2297 } | 1868 } |
| 2298 | 1869 |
| 2299 } // namespace entd | 1870 } // namespace entd |
| OLD | NEW |