Commit 7046027a authored by Ajanthan Asogamoorthy's avatar Ajanthan Asogamoorthy Committed by Facebook GitHub Bot

Implement getEkm

Summary: As title says, in this case implement just means call into openssl's implementation

Reviewed By: mingtaoy

Differential Revision: D33828545

fbshipit-source-id: 638adba4dd87dbccbc3886a512c52b5b8d44b5da
parent c17c984d
...@@ -444,6 +444,53 @@ std::string AsyncSSLSocket::getApplicationProtocol() const noexcept { ...@@ -444,6 +444,53 @@ std::string AsyncSSLSocket::getApplicationProtocol() const noexcept {
return ""; return "";
} }
std::unique_ptr<IOBuf> AsyncSSLSocket::getExportedKeyingMaterial(
folly::StringPiece label,
std::unique_ptr<IOBuf> context,
uint16_t length) const {
if (!ssl_ || sslState_ != STATE_ESTABLISHED) {
return nullptr;
}
/*
* We would like to only export EKM in the case where the extended master
* secret is used (per rfc7627). Note that for TLS1.3 this is by default. For
* TLS1.2 this has to be negotiated, so we will check that specifically. The
* usage of extended master secret prevents synchronization of master secrets
* across sessions.
*/
if (getSSLVersion() < TLS1_2_VERSION) {
return nullptr;
}
if (getSSLVersion() == TLS1_2_VERSION && !SSL_get_extms_support(ssl_.get())) {
return nullptr;
}
auto buf = IOBuf::create(length);
const unsigned char* contextBuf = nullptr;
size_t contextLength = 0;
if (context) {
auto contextBytes = context->coalesce();
contextBuf = contextBytes.data();
contextLength = contextBytes.size();
}
if (SSL_export_keying_material(
ssl_.get(),
buf->writableTail(),
(size_t)length,
label.data(),
label.size(),
contextBuf,
contextLength,
contextBuf != nullptr) != 1) {
return nullptr;
}
buf->append(length);
return buf;
}
void AsyncSSLSocket::setSupportedApplicationProtocols( void AsyncSSLSocket::setSupportedApplicationProtocols(
const std::vector<std::string>& supportedProtocols) { const std::vector<std::string>& supportedProtocols) {
encodedAlpn_ = OpenSSLUtils::encodeALPNString(supportedProtocols); encodedAlpn_ = OpenSSLUtils::encodeALPNString(supportedProtocols);
......
...@@ -393,6 +393,11 @@ class AsyncSSLSocket : public AsyncSocket { ...@@ -393,6 +393,11 @@ class AsyncSSLSocket : public AsyncSocket {
return "TLS"; return "TLS";
} }
std::unique_ptr<folly::IOBuf> getExportedKeyingMaterial(
folly::StringPiece label,
std::unique_ptr<IOBuf> context,
uint16_t length) const override;
void setEorTracking(bool track) override; void setEorTracking(bool track) override;
size_t getRawBytesWritten() const override; size_t getRawBytesWritten() const override;
size_t getRawBytesReceived() const override; size_t getRawBytesReceived() const override;
......
...@@ -1105,6 +1105,67 @@ TEST(AsyncSSLSocketTest, SSLParseClientHelloSuccess) { ...@@ -1105,6 +1105,67 @@ TEST(AsyncSSLSocketTest, SSLParseClientHelloSuccess) {
EXPECT_TRUE(!server.handshakeError_); EXPECT_TRUE(!server.handshakeError_);
} }
TEST(AsyncSSLSocketTest, SSLGetEKM) {
EventBase eventBase;
auto clientCtx = std::make_shared<SSLContext>();
auto serverCtx = std::make_shared<SSLContext>();
NetworkSocket fds[2];
getfds(fds);
getctx(clientCtx, serverCtx);
AsyncSSLSocket::UniquePtr clientSock(
new AsyncSSLSocket(clientCtx, &eventBase, fds[0], false));
AsyncSSLSocket::UniquePtr serverSock(
new AsyncSSLSocket(serverCtx, &eventBase, fds[1], true));
EXPECT_EQ(
nullptr, clientSock->getExportedKeyingMaterial("test", nullptr, 12));
serverSock->sslAccept(nullptr, std::chrono::milliseconds::zero());
clientSock->sslConn(nullptr, std::chrono::milliseconds::zero());
eventBase.loop();
auto ekm = clientSock->getExportedKeyingMaterial("test", nullptr, 32);
EXPECT_NE(nullptr, ekm);
EXPECT_EQ(ekm->computeChainDataLength(), 32);
// non null context
EXPECT_NE(
nullptr,
clientSock->getExportedKeyingMaterial(
"test", IOBuf::copyBuffer("haha"), 32));
// empty label
EXPECT_NE(
nullptr,
clientSock->getExportedKeyingMaterial("", IOBuf::copyBuffer("haha"), 32));
auto serverEkm = serverSock->getExportedKeyingMaterial("test", nullptr, 32);
EXPECT_TRUE(folly::IOBufEqualTo{}(ekm, serverEkm));
}
TEST(AsyncSSLSocketTest, SSLGetEKMFailsOnTLS10) {
EventBase eventBase;
auto clientCtx = std::make_shared<SSLContext>();
auto serverCtx = std::make_shared<SSLContext>();
SSL_CTX_set_max_proto_version(serverCtx->getSSLCtx(), TLS1_VERSION);
NetworkSocket fds[2];
getfds(fds);
getctx(clientCtx, serverCtx);
AsyncSSLSocket::UniquePtr clientSock(
new AsyncSSLSocket(clientCtx, &eventBase, fds[0], false));
AsyncSSLSocket::UniquePtr serverSock(
new AsyncSSLSocket(serverCtx, &eventBase, fds[1], true));
serverSock->sslAccept(nullptr, std::chrono::milliseconds::zero());
clientSock->sslConn(nullptr, std::chrono::milliseconds::zero());
eventBase.loop();
auto ekm = clientSock->getExportedKeyingMaterial("test", nullptr, 32);
EXPECT_EQ(nullptr, ekm);
}
/** /**
* Verify that server is able to get client cert by getPeerCert() API. * Verify that server is able to get client cert by getPeerCert() API.
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment