First working version of the confirmationui HAL service

This implementation does not provide any security guaranties.
 * The input method (NotSoSecureInput) runs a crypto protocols that is
   sufficiently secure IFF the end point is implemented on a trustworthy
   secure input device. But since the endpoint is currently in the HAL
   service itself this implementation is not secure.
 * This implementation provides most of the functionality, but not the
   secure UI infrastructure required to run Android Protected
   Confirmation.

Bug: 146078942
Test: VtsHalConfirmationUIV1_0TargetTest
Change-Id: I14717b5fa4ef15db960cdd506b8c6fe5369aec8d
diff --git a/trusty/confirmationui/TrustyApp.cpp b/trusty/confirmationui/TrustyApp.cpp
new file mode 100644
index 0000000..e4c68f9
--- /dev/null
+++ b/trusty/confirmationui/TrustyApp.cpp
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "TrustyApp.h"
+
+#include <android-base/logging.h>
+#include <sys/uio.h>
+#include <trusty/tipc.h>
+
+namespace android {
+namespace trusty {
+
+// 0x1000 is the message buffer size but we need to leave some space for a protocol header.
+// This assures that packets can always be read/written in one read/write operation.
+static constexpr const uint32_t kPacketSize = 0x1000 - 32;
+
+enum class PacketType : uint32_t {
+    SND,
+    RCV,
+    ACK,
+};
+
+struct PacketHeader {
+    PacketType type;
+    uint32_t remaining;
+};
+
+const char* toString(PacketType t) {
+    switch (t) {
+    case PacketType::SND:
+        return "SND";
+    case PacketType::RCV:
+        return "RCV";
+    case PacketType::ACK:
+        return "ACK";
+    default:
+        return "UNKNOWN";
+    }
+}
+
+static constexpr const uint32_t kHeaderSize = sizeof(PacketHeader);
+static constexpr const uint32_t kPayloadSize = kPacketSize - kHeaderSize;
+
+ssize_t TrustyRpc(int handle, const uint8_t* obegin, const uint8_t* oend, uint8_t* ibegin,
+                  uint8_t* iend) {
+    while (obegin != oend) {
+        PacketHeader header = {
+            .type = PacketType::SND,
+            .remaining = uint32_t(oend - obegin),
+        };
+        uint32_t body_size = std::min(kPayloadSize, header.remaining);
+        iovec iov[] = {
+            {
+                .iov_base = &header,
+                .iov_len = kHeaderSize,
+            },
+            {
+                .iov_base = const_cast<uint8_t*>(obegin),
+                .iov_len = body_size,
+            },
+        };
+        int rc = writev(handle, iov, 2);
+        if (!rc) {
+            PLOG(ERROR) << "Error sending SND message. " << rc;
+            return rc;
+        }
+
+        obegin += body_size;
+
+        rc = read(handle, &header, kHeaderSize);
+        if (!rc) {
+            PLOG(ERROR) << "Error reading ACK. " << rc;
+            return rc;
+        }
+
+        if (header.type != PacketType::ACK || header.remaining != oend - obegin) {
+            LOG(ERROR) << "malformed ACK";
+            return -1;
+        }
+    }
+
+    ssize_t remaining = 0;
+    auto begin = ibegin;
+    do {
+        PacketHeader header = {
+            .type = PacketType::RCV,
+            .remaining = 0,
+        };
+
+        iovec iov[] = {
+            {
+                .iov_base = &header,
+                .iov_len = kHeaderSize,
+            },
+            {
+                .iov_base = begin,
+                .iov_len = uint32_t(iend - begin),
+            },
+        };
+
+        ssize_t rc = writev(handle, iov, 1);
+        if (!rc) {
+            PLOG(ERROR) << "Error sending RCV message. " << rc;
+            return rc;
+        }
+
+        rc = readv(handle, iov, 2);
+        if (rc < 0) {
+            PLOG(ERROR) << "Error reading response. " << rc;
+            return rc;
+        }
+
+        uint32_t body_size = std::min(kPayloadSize, header.remaining);
+        if (body_size != rc - kHeaderSize) {
+            LOG(ERROR) << "Unexpected amount of data: " << rc;
+            return -1;
+        }
+
+        remaining = header.remaining - body_size;
+        begin += body_size;
+    } while (remaining);
+
+    return begin - ibegin;
+}
+
+TrustyApp::TrustyApp(const std::string& path, const std::string& appname)
+    : handle_(kInvalidHandle) {
+    handle_ = tipc_connect(path.c_str(), appname.c_str());
+    if (handle_ == kInvalidHandle) {
+        LOG(ERROR) << AT << "failed to connect to Trusty TA \"" << appname << "\" using dev:"
+                   << "\"" << path << "\"";
+    }
+    LOG(INFO) << AT << "succeeded to connect to Trusty TA \"" << appname << "\"";
+}
+TrustyApp::~TrustyApp() {
+    if (handle_ != kInvalidHandle) {
+        tipc_close(handle_);
+    }
+    LOG(INFO) << "Done shutting down TrustyApp";
+}
+
+}  // namespace trusty
+}  // namespace android