rsa_private_key_openssl.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
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)
75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <openssl/bio.h>
85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <openssl/bn.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <openssl/evp.h>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <openssl/pkcs12.h>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <openssl/rsa.h>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/openssl_util.h"
16116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "crypto/scoped_openssl_types.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace crypto {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Function pointer definition, for injecting the required key export function
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// into ExportKey, below. The supplied function should export EVP_PKEY into
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the supplied BIO, returning 1 on success or 0 on failure.
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef int (ExportFunction)(BIO*, EVP_PKEY*);
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper to export |key| into |output| via the specified ExportFunction.
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExportKey(EVP_PKEY* key,
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               ExportFunction export_fn,
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               std::vector<uint8>* output) {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!key)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OpenSSLErrStackTracer err_tracer(FROM_HERE);
35116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ScopedBIO bio(BIO_new(BIO_s_mem()));
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int res = export_fn(bio.get(), key);
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!res)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* data = NULL;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  long len = BIO_get_mem_data(bio.get(), &data);
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!data || len < 0)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output->assign(data, data + len);
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RSAPrivateKey* RSAPrivateKey::Create(uint16 num_bits) {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OpenSSLErrStackTracer err_tracer(FROM_HERE);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
56116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ScopedRSA rsa_key(RSA_new());
57116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ScopedBIGNUM bn(BN_new());
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!rsa_key.get() || !bn.get() || !BN_set_word(bn.get(), 65537L))
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!RSA_generate_key_ex(rsa_key.get(), num_bits, bn.get(), NULL))
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->key_ = EVP_PKEY_new();
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result->key_ || !EVP_PKEY_set1_RSA(result->key_, rsa_key.get()))
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result.release();
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo(
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<uint8>& input) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (input.empty())
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OpenSSLErrStackTracer err_tracer(FROM_HERE);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // BIO_new_mem_buf is not const aware, but it does not modify the buffer.
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* data = reinterpret_cast<char*>(const_cast<uint8*>(&input[0]));
81116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ScopedBIO bio(BIO_new_mem_buf(data, input.size()));
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!bio.get())
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Importing is a little more involved than exporting, as we must first
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // PKCS#8 decode the input, and then import the EVP_PKEY from Private Key
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Info structure returned.
88116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ScopedOpenSSL<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free>::Type p8inf(
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      d2i_PKCS8_PRIV_KEY_INFO_bio(bio.get(), NULL));
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!p8inf.get())
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->key_ = EVP_PKCS82PKEY(p8inf.get());
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result->key_)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result.release();
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RSAPrivateKey::RSAPrivateKey()
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : key_(NULL) {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RSAPrivateKey::~RSAPrivateKey() {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (key_)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EVP_PKEY_free(key_);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RSAPrivateKey* RSAPrivateKey::Copy() const {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RSAPrivateKey> copy(new RSAPrivateKey());
112116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ScopedRSA rsa(EVP_PKEY_get1_RSA(key_));
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!rsa)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  copy->key_ = EVP_PKEY_new();
116116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!EVP_PKEY_set1_RSA(copy->key_, rsa.get()))
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return copy.release();
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8>* output) const {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ExportKey(key_, i2d_PKCS8PrivateKeyInfo_bio, output);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool RSAPrivateKey::ExportPublicKey(std::vector<uint8>* output) const {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ExportKey(key_, i2d_PUBKEY_bio, output);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace crypto
130