1116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
2116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// found in the LICENSE file.
4116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
5116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/common/extensions/api/networking_private/networking_private_crypto.h"
6116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <openssl/digest.h>
85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <openssl/evp.h>
95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <openssl/rsa.h>
105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <openssl/x509.h>
115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
12116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/logging.h"
135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/strings/string_util.h"
145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "crypto/openssl_util.h"
155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "crypto/rsa_private_key.h"
165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "crypto/scoped_openssl_types.h"
175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/cert/pem_tokenizer.h"
18116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace {
205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)typedef crypto::ScopedOpenSSL<X509, X509_free>::Type ScopedX509;
22116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Parses |pem_data| for a PEM block of |pem_type|.
245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Returns true if a |pem_type| block is found, storing the decoded result in
255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// |der_output|.
265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool GetDERFromPEM(const std::string& pem_data,
275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   const std::string& pem_type,
285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   std::vector<uint8_t>* der_output) {
295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::vector<std::string> headers;
305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  headers.push_back(pem_type);
315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  net::PEMTokenizer pem_tok(pem_data, headers);
325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!pem_tok.GetNext()) {
335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return false;
345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  der_output->assign(pem_tok.data().begin(), pem_tok.data().end());
375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return true;
38116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
39116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}  // namespace
415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)namespace networking_private_crypto {
436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool VerifyCredentials(const std::string& certificate,
456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                       const std::string& signature,
466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                       const std::string& data,
476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                       const std::string& connected_mac) {
485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  crypto::EnsureOpenSSLInit();
495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::vector<uint8_t> cert_data;
525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!GetDERFromPEM(certificate, "CERTIFICATE", &cert_data)) {
535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(ERROR) << "Failed to parse certificate.";
545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return false;
555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Parse into an OpenSSL X509.
585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const uint8_t* ptr = cert_data.empty() ? NULL : &cert_data[0];
595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const uint8_t* end = ptr + cert_data.size();
605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ScopedX509 cert(d2i_X509(NULL, &ptr, cert_data.size()));
615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!cert || ptr != end) {
625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(ERROR) << "Failed to parse certificate.";
635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return false;
645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Import the trusted public key.
675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ptr = kTrustedCAPublicKeyDER;
685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  crypto::ScopedRSA ca_public_key_rsa(
695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      d2i_RSAPublicKey(NULL, &ptr, kTrustedCAPublicKeyDERLength));
705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!ca_public_key_rsa ||
715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      ptr != kTrustedCAPublicKeyDER + kTrustedCAPublicKeyDERLength) {
725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    NOTREACHED();
735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(ERROR) << "Failed to import trusted public key.";
745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return false;
755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  crypto::ScopedEVP_PKEY ca_public_key(EVP_PKEY_new());
775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!ca_public_key ||
785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      !EVP_PKEY_set1_RSA(ca_public_key.get(), ca_public_key_rsa.get())) {
795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(ERROR) << "Failed to initialize EVP_PKEY";
805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return false;
815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Check that the certificate is signed by the trusted public key.
845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (X509_verify(cert.get(), ca_public_key.get()) <= 0) {
855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(ERROR) << "Certificate is not issued by the trusted CA.";
865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return false;
875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Check that the device listed in the certificate is correct.
905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Something like evt_e161 001a11ffacdf
915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::string common_name;
925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int common_name_length = X509_NAME_get_text_by_NID(
935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      cert->cert_info->subject, NID_commonName, NULL, 0);
945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (common_name_length < 0) {
955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(ERROR) << "Certificate does not have common name.";
965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return false;
975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (common_name_length > 0) {
995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    common_name_length = X509_NAME_get_text_by_NID(
1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        cert->cert_info->subject,
1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        NID_commonName,
1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        WriteInto(&common_name, common_name_length + 1),
1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        common_name_length + 1);
1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    DCHECK_EQ((int)common_name.size(), common_name_length);
1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (common_name_length < 0) {
1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      LOG(ERROR) << "Certificate does not have common name.";
1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      return false;
1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    common_name.resize(common_name_length);
1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::string translated_mac;
1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::RemoveChars(connected_mac, ":", &translated_mac);
1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!EndsWith(common_name, translated_mac, false)) {
1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(ERROR) << "MAC addresses don't match.";
1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return false;
1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Make sure that the certificate matches the unsigned data presented.
1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Verify that the |signature| matches |data|.
1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  crypto::ScopedEVP_PKEY public_key(X509_get_pubkey(cert.get()));
1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!public_key) {
1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(ERROR) << "Unable to extract public key from certificate.";
1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return false;
1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  crypto::ScopedEVP_MD_CTX ctx(EVP_MD_CTX_create());
1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!ctx) {
1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(ERROR) << "Unable to allocate EVP_MD_CTX.";
1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return false;
1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (EVP_DigestVerifyInit(
1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          ctx.get(), NULL, EVP_sha1(), NULL, public_key.get()) <= 0 ||
1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      EVP_DigestVerifyUpdate(ctx.get(), data.data(), data.size()) <= 0 ||
1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      EVP_DigestVerifyFinal(ctx.get(),
1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            reinterpret_cast<const uint8_t*>(signature.data()),
1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            signature.size()) <= 0) {
1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(ERROR) << "Signed blobs did not match.";
1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return false;
1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return true;
142116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
143116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
1446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool EncryptByteString(const std::vector<uint8_t>& pub_key_der,
1456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                       const std::string& data,
1466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                       std::vector<uint8_t>* encrypted_output) {
1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  crypto::EnsureOpenSSLInit();
1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const uint8_t* ptr = pub_key_der.empty() ? NULL : &pub_key_der[0];
1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const uint8_t* end = ptr + pub_key_der.size();
1525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  crypto::ScopedRSA rsa(d2i_RSAPublicKey(NULL, &ptr, pub_key_der.size()));
1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!rsa || ptr != end || RSA_size(rsa.get()) == 0) {
1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(ERROR) << "Failed to parse public key";
1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return false;
1565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_ptr<uint8_t[]> rsa_output(new uint8_t[RSA_size(rsa.get())]);
1595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int encrypted_length =
1605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      RSA_public_encrypt(data.size(),
1615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                         reinterpret_cast<const uint8_t*>(data.data()),
1625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                         rsa_output.get(),
1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                         rsa.get(),
1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                         RSA_PKCS1_PADDING);
1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (encrypted_length < 0) {
1665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(ERROR) << "Error during decryption";
1675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return false;
1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  encrypted_output->assign(rsa_output.get(),
1705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                           rsa_output.get() + encrypted_length);
1715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return true;
172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
173116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
1746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool DecryptByteString(const std::string& private_key_pem,
1756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                       const std::vector<uint8_t>& encrypted_data,
1766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                       std::string* decrypted_output) {
1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  crypto::EnsureOpenSSLInit();
1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
1795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::vector<uint8_t> private_key_data;
1815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!GetDERFromPEM(private_key_pem, "PRIVATE KEY", &private_key_data)) {
1825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(ERROR) << "Failed to parse private key PEM.";
1835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return false;
1845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_ptr<crypto::RSAPrivateKey> private_key(
1865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(private_key_data));
1875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!private_key || !private_key->key()) {
1885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(ERROR) << "Failed to parse private key DER.";
1895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return false;
1905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  crypto::ScopedRSA rsa(EVP_PKEY_get1_RSA(private_key->key()));
1935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!rsa || RSA_size(rsa.get()) == 0) {
1945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(ERROR) << "Failed to get RSA key.";
1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return false;
1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_ptr<uint8_t[]> rsa_output(new uint8_t[RSA_size(rsa.get())]);
1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int output_length = RSA_private_decrypt(encrypted_data.size(),
2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                          &encrypted_data[0],
2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                          rsa_output.get(),
2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                          rsa.get(),
2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                          RSA_PKCS1_PADDING);
2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (output_length < 0) {
2055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(ERROR) << "Error during decryption.";
2065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return false;
2075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  decrypted_output->assign(reinterpret_cast<char*>(rsa_output.get()),
2095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                           output_length);
2105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return true;
211116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
2126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}  // namespace networking_private_crypto
214