1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 3513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// found in the LICENSE file. 4513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 5ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "crypto/rsa_private_key.h" 6513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 74a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include <openssl/evp.h> 84a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include <openssl/pkcs12.h> 94a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include <openssl/rsa.h> 104a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 11513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/logging.h" 12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h" 134a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "base/stl_util-inl.h" 14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "crypto/openssl_util.h" 15513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsennamespace crypto { 17513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 184a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochnamespace { 194a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 204a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// Function pointer definition, for injecting the required key export function 214a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// into ExportKey, below. The supplied function should export EVP_PKEY into 224a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// the supplied BIO, returning 1 on success or 0 on failure. 234a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochtypedef int (ExportFunction)(BIO*, EVP_PKEY*); 244a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 254a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// Helper to export |key| into |output| via the specified ExportFunction. 264a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochbool ExportKey(EVP_PKEY* key, 274a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch ExportFunction export_fn, 284a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch std::vector<uint8>* output) { 294a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (!key) 304a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return false; 314a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 32201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch OpenSSLErrStackTracer err_tracer(FROM_HERE); 334a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch ScopedOpenSSL<BIO, BIO_free_all> bio(BIO_new(BIO_s_mem())); 344a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 354a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch int res = export_fn(bio.get(), key); 364a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (!res) 374a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return false; 384a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 394a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch char* data = NULL; 404a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch long len = BIO_get_mem_data(bio.get(), &data); 414a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (!data || len < 0) 424a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return false; 434a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 444a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch STLAssignToVector(output, reinterpret_cast<const uint8*>(data), len); 454a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return true; 46513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 47513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 484a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch} // namespace 494a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 50513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// static 51513209b27ff55e2841eac0e4120199c23acce758Ben MurdochRSAPrivateKey* RSAPrivateKey::Create(uint16 num_bits) { 52201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch OpenSSLErrStackTracer err_tracer(FROM_HERE); 5321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 5421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen ScopedOpenSSL<RSA, RSA_free> rsa_key(RSA_new()); 5521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen ScopedOpenSSL<BIGNUM, BN_free> bn(BN_new()); 5621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!rsa_key.get() || !bn.get() || !BN_set_word(bn.get(), 65537L)) 5721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return NULL; 5821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 5921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!RSA_generate_key_ex(rsa_key.get(), num_bits, bn.get(), NULL)) 604a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return NULL; 614a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 624a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey); 634a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch result->key_ = EVP_PKEY_new(); 644a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (!result->key_ || !EVP_PKEY_set1_RSA(result->key_, rsa_key.get())) 654a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return NULL; 664a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 674a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return result.release(); 68513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 69513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 70513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// static 714a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben MurdochRSAPrivateKey* RSAPrivateKey::CreateSensitive(uint16 num_bits) { 72513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch NOTIMPLEMENTED(); 73513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return NULL; 74513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 75513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 76513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// static 77513209b27ff55e2841eac0e4120199c23acce758Ben MurdochRSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo( 78513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const std::vector<uint8>& input) { 79201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch OpenSSLErrStackTracer err_tracer(FROM_HERE); 804a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 814a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // BIO_new_mem_buf is not const aware, but it does not modify the buffer. 8221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen char* data = reinterpret_cast<char*>(const_cast<uint8*>( 8321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen vector_as_array(&input))); 844a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch ScopedOpenSSL<BIO, BIO_free_all> bio(BIO_new_mem_buf(data, input.size())); 854a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (!bio.get()) 864a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return NULL; 874a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 884a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // Importing is a little more involved than exporting, as we must first 894a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // PKCS#8 decode the input, and then import the EVP_PKEY from Private Key 904a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // Info structure returned. 914a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch ScopedOpenSSL<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free> p8inf( 924a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch d2i_PKCS8_PRIV_KEY_INFO_bio(bio.get(), NULL)); 934a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (!p8inf.get()) 944a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return NULL; 954a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 964a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey); 974a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch result->key_ = EVP_PKCS82PKEY(p8inf.get()); 984a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (!result->key_) 994a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return NULL; 1004a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 1014a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return result.release(); 102513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 103513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 104513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// static 105513209b27ff55e2841eac0e4120199c23acce758Ben MurdochRSAPrivateKey* RSAPrivateKey::CreateSensitiveFromPrivateKeyInfo( 106513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const std::vector<uint8>& input) { 1074a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch NOTIMPLEMENTED(); 1084a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return NULL; 109513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 110513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 111513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// static 112513209b27ff55e2841eac0e4120199c23acce758Ben MurdochRSAPrivateKey* RSAPrivateKey::FindFromPublicKeyInfo( 113513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const std::vector<uint8>& input) { 114513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch NOTIMPLEMENTED(); 115513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return NULL; 116513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 117513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 1184a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben MurdochRSAPrivateKey::RSAPrivateKey() 1194a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch : key_(NULL) { 120513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 121513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 122513209b27ff55e2841eac0e4120199c23acce758Ben MurdochRSAPrivateKey::~RSAPrivateKey() { 1234a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (key_) 1244a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch EVP_PKEY_free(key_); 125513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 126513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 127513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool RSAPrivateKey::ExportPrivateKey(std::vector<uint8>* output) { 1284a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return ExportKey(key_, i2d_PKCS8PrivateKeyInfo_bio, output); 129513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 130513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 131513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool RSAPrivateKey::ExportPublicKey(std::vector<uint8>* output) { 1324a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return ExportKey(key_, i2d_PUBKEY_bio, output); 133513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 134513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 135ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} // namespace crypto 136