binder: RpcServer / RpcSession add API for certs.

These APIs call into RpcTransportCtx::getCertificate
and RpcTransportClientCtx::addTrustedPeerCertificate,
respectively.

For RpcSession, peer (server) certificates are fixed when
it is constructed.

Test: binderRpcTest
Bug: 195166979
Change-Id: I0d1bd93042895aeb3ab1de4fe6b9d90e73d0d116
diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp
index 4c47005..22a7782 100644
--- a/libs/binder/RpcSession.cpp
+++ b/libs/binder/RpcSession.cpp
@@ -49,8 +49,7 @@
 
 using base::unique_fd;
 
-RpcSession::RpcSession(std::unique_ptr<RpcTransportCtxFactory> rpcTransportCtxFactory)
-      : mRpcTransportCtxFactory(std::move(rpcTransportCtxFactory)) {
+RpcSession::RpcSession(std::unique_ptr<RpcTransportCtx> ctx) : mCtx(std::move(ctx)) {
     LOG_RPC_DETAIL("RpcSession created %p", this);
 
     mState = std::make_unique<RpcState>();
@@ -63,11 +62,26 @@
                         "Should not be able to destroy a session with servers in use.");
 }
 
-sp<RpcSession> RpcSession::make(std::unique_ptr<RpcTransportCtxFactory> rpcTransportCtxFactory) {
+sp<RpcSession> RpcSession::make() {
     // Default is without TLS.
-    if (rpcTransportCtxFactory == nullptr)
-        rpcTransportCtxFactory = RpcTransportCtxFactoryRaw::make();
-    return sp<RpcSession>::make(std::move(rpcTransportCtxFactory));
+    return make(RpcTransportCtxFactoryRaw::make(), std::nullopt, std::nullopt);
+}
+
+sp<RpcSession> RpcSession::make(std::unique_ptr<RpcTransportCtxFactory> rpcTransportCtxFactory,
+                                std::optional<CertificateFormat> serverCertificateFormat,
+                                std::optional<std::string> serverCertificate) {
+    auto ctx = rpcTransportCtxFactory->newClientCtx();
+    if (ctx == nullptr) return nullptr;
+    LOG_ALWAYS_FATAL_IF(serverCertificateFormat.has_value() != serverCertificate.has_value());
+    if (serverCertificateFormat.has_value() && serverCertificate.has_value()) {
+        status_t status =
+                ctx->addTrustedPeerCertificate(*serverCertificateFormat, *serverCertificate);
+        if (status != OK) {
+            ALOGE("Cannot add trusted server certificate: %s", statusToString(status).c_str());
+            return nullptr;
+        }
+    }
+    return sp<RpcSession>::make(std::move(ctx));
 }
 
 void RpcSession::setMaxThreads(size_t threads) {
@@ -155,12 +169,7 @@
         return -savedErrno;
     }
 
-    auto ctx = mRpcTransportCtxFactory->newClientCtx();
-    if (ctx == nullptr) {
-        ALOGE("Unable to create RpcTransportCtx for null debugging client");
-        return NO_MEMORY;
-    }
-    auto server = ctx->newTransport(std::move(serverFd), mShutdownTrigger.get());
+    auto server = mCtx->newTransport(std::move(serverFd), mShutdownTrigger.get());
     if (server == nullptr) {
         ALOGE("Unable to set up RpcTransport");
         return UNKNOWN_ERROR;
@@ -529,15 +538,9 @@
 status_t RpcSession::initAndAddConnection(unique_fd fd, const RpcAddress& sessionId,
                                           bool incoming) {
     LOG_ALWAYS_FATAL_IF(mShutdownTrigger == nullptr);
-    auto ctx = mRpcTransportCtxFactory->newClientCtx();
-    if (ctx == nullptr) {
-        ALOGE("Unable to create client RpcTransportCtx with %s sockets",
-              mRpcTransportCtxFactory->toCString());
-        return NO_MEMORY;
-    }
-    auto server = ctx->newTransport(std::move(fd), mShutdownTrigger.get());
+    auto server = mCtx->newTransport(std::move(fd), mShutdownTrigger.get());
     if (server == nullptr) {
-        ALOGE("Unable to set up RpcTransport in %s context", mRpcTransportCtxFactory->toCString());
+        ALOGE("%s: Unable to set up RpcTransport", __PRETTY_FUNCTION__);
         return UNKNOWN_ERROR;
     }
 
@@ -692,6 +695,10 @@
     return false;
 }
 
+std::string RpcSession::getCertificate(CertificateFormat format) {
+    return mCtx->getCertificate(format);
+}
+
 status_t RpcSession::ExclusiveConnection::find(const sp<RpcSession>& session, ConnectionUse use,
                                                ExclusiveConnection* connection) {
     connection->mSession = session;