rsa_private_key_openssl.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/rsa_private_key.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <openssl/evp.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <openssl/pkcs12.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <openssl/rsa.h> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/openssl_util.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace crypto { 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Function pointer definition, for injecting the required key export function 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// into ExportKey, below. The supplied function should export EVP_PKEY into 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the supplied BIO, returning 1 on success or 0 on failure. 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef int (ExportFunction)(BIO*, EVP_PKEY*); 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper to export |key| into |output| via the specified ExportFunction. 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExportKey(EVP_PKEY* key, 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExportFunction export_fn, 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<uint8>* output) { 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!key) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OpenSSLErrStackTracer err_tracer(FROM_HERE); 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedOpenSSL<BIO, BIO_free_all> bio(BIO_new(BIO_s_mem())); 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int res = export_fn(bio.get(), key); 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!res) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* data = NULL; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) long len = BIO_get_mem_data(bio.get(), &data); 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!data || len < 0) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output->assign(data, data + len); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RSAPrivateKey* RSAPrivateKey::Create(uint16 num_bits) { 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OpenSSLErrStackTracer err_tracer(FROM_HERE); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedOpenSSL<RSA, RSA_free> rsa_key(RSA_new()); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedOpenSSL<BIGNUM, BN_free> bn(BN_new()); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!rsa_key.get() || !bn.get() || !BN_set_word(bn.get(), 65537L)) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!RSA_generate_key_ex(rsa_key.get(), num_bits, bn.get(), NULL)) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->key_ = EVP_PKEY_new(); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!result->key_ || !EVP_PKEY_set1_RSA(result->key_, rsa_key.get())) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result.release(); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RSAPrivateKey* RSAPrivateKey::CreateSensitive(uint16 num_bits) { 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTIMPLEMENTED(); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo( 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<uint8>& input) { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (input.empty()) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OpenSSLErrStackTracer err_tracer(FROM_HERE); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // BIO_new_mem_buf is not const aware, but it does not modify the buffer. 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* data = reinterpret_cast<char*>(const_cast<uint8*>(&input[0])); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedOpenSSL<BIO, BIO_free_all> bio(BIO_new_mem_buf(data, input.size())); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!bio.get()) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Importing is a little more involved than exporting, as we must first 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // PKCS#8 decode the input, and then import the EVP_PKEY from Private Key 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Info structure returned. 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedOpenSSL<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free> p8inf( 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) d2i_PKCS8_PRIV_KEY_INFO_bio(bio.get(), NULL)); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!p8inf.get()) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->key_ = EVP_PKCS82PKEY(p8inf.get()); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!result->key_) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result.release(); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RSAPrivateKey* RSAPrivateKey::CreateSensitiveFromPrivateKeyInfo( 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<uint8>& input) { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTIMPLEMENTED(); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RSAPrivateKey* RSAPrivateKey::FindFromPublicKeyInfo( 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<uint8>& input) { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTIMPLEMENTED(); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RSAPrivateKey::RSAPrivateKey() 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : key_(NULL) { 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RSAPrivateKey::~RSAPrivateKey() { 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (key_) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVP_PKEY_free(key_); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RSAPrivateKey* RSAPrivateKey::Copy() const { 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<RSAPrivateKey> copy(new RSAPrivateKey()); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RSA* rsa = EVP_PKEY_get1_RSA(key_); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!rsa) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) copy->key_ = EVP_PKEY_new(); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!EVP_PKEY_set1_RSA(copy->key_, rsa)) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return copy.release(); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8>* output) const { 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ExportKey(key_, i2d_PKCS8PrivateKeyInfo_bio, output); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool RSAPrivateKey::ExportPublicKey(std::vector<uint8>* output) const { 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ExportKey(key_, i2d_PUBKEY_bio, output); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace crypto 147