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