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