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