Home | History | Annotate | Download | only in crypto
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "crypto/rsa_private_key.h"
      6 
      7 #include <stdint.h>
      8 
      9 #include <memory>
     10 #include <utility>
     11 
     12 #include "base/logging.h"
     13 #include "crypto/openssl_util.h"
     14 #include "third_party/boringssl/src/include/openssl/bn.h"
     15 #include "third_party/boringssl/src/include/openssl/bytestring.h"
     16 #include "third_party/boringssl/src/include/openssl/evp.h"
     17 #include "third_party/boringssl/src/include/openssl/mem.h"
     18 #include "third_party/boringssl/src/include/openssl/rsa.h"
     19 
     20 namespace crypto {
     21 
     22 // static
     23 std::unique_ptr<RSAPrivateKey> RSAPrivateKey::Create(uint16_t num_bits) {
     24   OpenSSLErrStackTracer err_tracer(FROM_HERE);
     25 
     26   bssl::UniquePtr<RSA> rsa_key(RSA_new());
     27   bssl::UniquePtr<BIGNUM> bn(BN_new());
     28   if (!rsa_key.get() || !bn.get() || !BN_set_word(bn.get(), 65537L))
     29     return nullptr;
     30 
     31   if (!RSA_generate_key_ex(rsa_key.get(), num_bits, bn.get(), nullptr))
     32     return nullptr;
     33 
     34   std::unique_ptr<RSAPrivateKey> result(new RSAPrivateKey);
     35   result->key_.reset(EVP_PKEY_new());
     36   if (!result->key_ || !EVP_PKEY_set1_RSA(result->key_.get(), rsa_key.get()))
     37     return nullptr;
     38 
     39   return result;
     40 }
     41 
     42 // static
     43 std::unique_ptr<RSAPrivateKey> RSAPrivateKey::CreateFromPrivateKeyInfo(
     44     const std::vector<uint8_t>& input) {
     45   OpenSSLErrStackTracer err_tracer(FROM_HERE);
     46 
     47   CBS cbs;
     48   CBS_init(&cbs, input.data(), input.size());
     49   bssl::UniquePtr<EVP_PKEY> pkey(EVP_parse_private_key(&cbs));
     50   if (!pkey || CBS_len(&cbs) != 0 || EVP_PKEY_id(pkey.get()) != EVP_PKEY_RSA)
     51     return nullptr;
     52 
     53   std::unique_ptr<RSAPrivateKey> result(new RSAPrivateKey);
     54   result->key_ = std::move(pkey);
     55   return result;
     56 }
     57 
     58 // static
     59 std::unique_ptr<RSAPrivateKey> RSAPrivateKey::CreateFromKey(EVP_PKEY* key) {
     60   DCHECK(key);
     61   if (EVP_PKEY_type(key->type) != EVP_PKEY_RSA)
     62     return nullptr;
     63   std::unique_ptr<RSAPrivateKey> copy(new RSAPrivateKey);
     64   EVP_PKEY_up_ref(key);
     65   copy->key_.reset(key);
     66   return copy;
     67 }
     68 
     69 RSAPrivateKey::RSAPrivateKey() {}
     70 
     71 RSAPrivateKey::~RSAPrivateKey() {}
     72 
     73 std::unique_ptr<RSAPrivateKey> RSAPrivateKey::Copy() const {
     74   std::unique_ptr<RSAPrivateKey> copy(new RSAPrivateKey);
     75   bssl::UniquePtr<RSA> rsa(EVP_PKEY_get1_RSA(key_.get()));
     76   if (!rsa)
     77     return nullptr;
     78   copy->key_.reset(EVP_PKEY_new());
     79   if (!EVP_PKEY_set1_RSA(copy->key_.get(), rsa.get()))
     80     return nullptr;
     81   return copy;
     82 }
     83 
     84 bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8_t>* output) const {
     85   OpenSSLErrStackTracer err_tracer(FROM_HERE);
     86   uint8_t *der;
     87   size_t der_len;
     88   bssl::ScopedCBB cbb;
     89   if (!CBB_init(cbb.get(), 0) ||
     90       !EVP_marshal_private_key(cbb.get(), key_.get()) ||
     91       !CBB_finish(cbb.get(), &der, &der_len)) {
     92     return false;
     93   }
     94   output->assign(der, der + der_len);
     95   OPENSSL_free(der);
     96   return true;
     97 }
     98 
     99 bool RSAPrivateKey::ExportPublicKey(std::vector<uint8_t>* output) const {
    100   OpenSSLErrStackTracer err_tracer(FROM_HERE);
    101   uint8_t *der;
    102   size_t der_len;
    103   bssl::ScopedCBB cbb;
    104   if (!CBB_init(cbb.get(), 0) ||
    105       !EVP_marshal_public_key(cbb.get(), key_.get()) ||
    106       !CBB_finish(cbb.get(), &der, &der_len)) {
    107     return false;
    108   }
    109   output->assign(der, der + der_len);
    110   OPENSSL_free(der);
    111   return true;
    112 }
    113 
    114 }  // namespace crypto
    115