Index: components/gcm_driver/crypto/p256_key_util.cc |
diff --git a/components/gcm_driver/crypto/p256_key_util.cc b/components/gcm_driver/crypto/p256_key_util.cc |
index 24e8da5d62b947f58d1f8a2921ae85fce4e04738..86b543de45d3916b5d42519eefcd42b0cd01c270 100644 |
--- a/components/gcm_driver/crypto/p256_key_util.cc |
+++ b/components/gcm_driver/crypto/p256_key_util.cc |
@@ -4,6 +4,9 @@ |
#include "components/gcm_driver/crypto/p256_key_util.h" |
+#include <openssl/ec.h> |
+#include <openssl/ecdh.h> |
+#include <openssl/evp.h> |
#include <stddef.h> |
#include <stdint.h> |
@@ -11,7 +14,9 @@ |
#include <vector> |
#include "base/logging.h" |
+#include "base/strings/string_util.h" |
#include "crypto/ec_private_key.h" |
+#include "crypto/scoped_openssl_types.h" |
namespace gcm { |
@@ -88,4 +93,55 @@ bool CreateP256KeyPair(std::string* out_private_key, |
return true; |
} |
+bool ComputeSharedP256Secret(const base::StringPiece& private_key, |
+ const base::StringPiece& public_key_x509, |
+ const base::StringPiece& peer_public_key, |
+ std::string* out_shared_secret) { |
+ DCHECK(out_shared_secret); |
+ |
+ std::unique_ptr<crypto::ECPrivateKey> local_key_pair( |
+ crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( |
+ "" /* no password */, |
+ std::vector<uint8_t>(private_key.data(), |
+ private_key.data() + private_key.size()), |
+ std::vector<uint8_t>( |
+ public_key_x509.data(), |
+ public_key_x509.data() + public_key_x509.size()))); |
+ |
+ if (!local_key_pair) { |
+ DLOG(ERROR) << "Unable to create the local key pair."; |
+ return false; |
+ } |
+ |
+ crypto::ScopedEC_KEY ec_private_key( |
+ EVP_PKEY_get1_EC_KEY(local_key_pair->key())); |
+ |
+ if (!ec_private_key || !EC_KEY_check_key(ec_private_key.get())) { |
+ DLOG(ERROR) << "The private key is invalid."; |
+ return false; |
+ } |
+ |
+ crypto::ScopedEC_POINT point( |
+ EC_POINT_new(EC_KEY_get0_group(ec_private_key.get()))); |
+ |
+ if (!point || |
+ !EC_POINT_oct2point(EC_KEY_get0_group(ec_private_key.get()), point.get(), |
+ reinterpret_cast<const uint8_t*>( |
+ peer_public_key.data()), |
+ peer_public_key.size(), nullptr)) { |
+ DLOG(ERROR) << "Can't convert peer public value to curve point."; |
+ return false; |
+ } |
+ |
+ uint8_t result[kFieldBytes]; |
+ if (ECDH_compute_key(result, sizeof(result), point.get(), |
+ ec_private_key.get(), nullptr) != sizeof(result)) { |
+ DLOG(ERROR) << "Unable to compute the ECDH shared secret."; |
+ return false; |
+ } |
+ |
+ out_shared_secret->assign(reinterpret_cast<char*>(result), sizeof(result)); |
+ return true; |
+} |
+ |
} // namespace gcm |