Skip to content

Commit e4cfd54

Browse files
authored
Added TLSContext::registerPrivateKey() [CBL-8083] (#2453)
This is a workaround for the problem of how to use a custom (external) PrivateKey with the outgoing version of TLSCodec::wrapSocketFactoryInTLS, which does not take a TLSContext and has no way to convey such an object to the code that eventually creates a TLSContext.
1 parent c78e727 commit e4cfd54

2 files changed

Lines changed: 29 additions & 0 deletions

File tree

Networking/TLSContext.cc

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "Logging.hh"
2121
#include "fleece/Fleece.hh"
2222
#include "sockpp/mbedtls_context.h"
23+
#include <mutex>
2324
#include <string>
2425

2526
using namespace std;
@@ -29,6 +30,12 @@ using namespace fleece;
2930
namespace litecore::net {
3031
using namespace crypto;
3132

33+
#ifdef COUCHBASE_ENTERPRISE
34+
static unordered_map<alloc_slice, Ref<PrivateKey>>* sPrivateKeyMap;
35+
static mutex sPrivateKeyMapMutex;
36+
#endif
37+
38+
3239
Retained<TLSContext> TLSContext::fromReplicatorOptions(Dict options, PrivateKey* externalKey,
3340
const CertAuthCallback& certAuthCallback) {
3441
if ( !options ) return nullptr;
@@ -52,6 +59,15 @@ namespace litecore::net {
5259
slice certData = authDict[kC4ReplicatorAuthClientCert].asData();
5360
if ( !certData )
5461
error::_throw(error::InvalidParameter, "Missing TLS client cert in C4Replicator config");
62+
#ifdef COUCHBASE_ENTERPRISE
63+
if ( !externalKey ) {
64+
unique_lock lock(sPrivateKeyMapMutex);
65+
if ( sPrivateKeyMap ) {
66+
if ( auto i = sPrivateKeyMap->find(alloc_slice(certData)); i != sPrivateKeyMap->end() )
67+
externalKey = i->second;
68+
}
69+
}
70+
#endif
5571
if ( externalKey ) {
5672
Retained<Cert> cert = make_retained<Cert>(certData);
5773
tlsContext->setIdentity(new Identity(cert, externalKey));
@@ -110,6 +126,14 @@ namespace litecore::net {
110126

111127
return tlsContext;
112128
}
129+
130+
void TLSContext::registerPrivateKey(slice certData, PrivateKey* key) {
131+
unique_lock lock(sPrivateKeyMapMutex);
132+
if ( !sPrivateKeyMap ) sPrivateKeyMap = new unordered_map<alloc_slice, Ref<PrivateKey>>();
133+
if ( key ) sPrivateKeyMap->insert_or_assign(alloc_slice(certData), key);
134+
else
135+
sPrivateKeyMap->erase(alloc_slice(certData));
136+
}
113137
#endif
114138

115139
TLSContext::TLSContext(role_t role)

Networking/TLSContext.hh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,11 @@ namespace litecore::net {
7979
/// to the config's `certAuthCallback`, if any.
8080
static fleece::Ref<TLSContext> fromListenerOptions(const C4TLSConfig* config,
8181
C4Listener* C4NULLABLE c4Listener);
82+
83+
/// Globally registers a PrivateKey instance to use with the given certificate,
84+
/// or unregisters if the key is null.
85+
/// This can be used when you have no direct access to the code that creates the TLSContext.
86+
static void registerPrivateKey(fleece::slice certData, crypto::PrivateKey* C4NULLABLE);
8287
#endif
8388

8489
/// Creates a default TLSContext with either the client or server role.

0 commit comments

Comments
 (0)