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) 1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// static 1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciRSAPrivateKey* RSAPrivateKey::CreateFromKey(EVP_PKEY* key) { 1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(key); 1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (EVP_PKEY_type(key->type) != EVP_PKEY_RSA) 1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return NULL; 1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci RSAPrivateKey* copy = new RSAPrivateKey(); 1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci copy->key_ = EVP_PKEY_dup(key); 1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return copy; 1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RSAPrivateKey::RSAPrivateKey() 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : key_(NULL) { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RSAPrivateKey::~RSAPrivateKey() { 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (key_) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVP_PKEY_free(key_); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RSAPrivateKey* RSAPrivateKey::Copy() const { 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<RSAPrivateKey> copy(new RSAPrivateKey()); 122116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ScopedRSA rsa(EVP_PKEY_get1_RSA(key_)); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!rsa) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) copy->key_ = EVP_PKEY_new(); 126116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!EVP_PKEY_set1_RSA(copy->key_, rsa.get())) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return copy.release(); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8>* output) const { 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ExportKey(key_, i2d_PKCS8PrivateKeyInfo_bio, output); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool RSAPrivateKey::ExportPublicKey(std::vector<uint8>* output) const { 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ExportKey(key_, i2d_PUBKEY_bio, output); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace crypto 140