1 //
2 // Copyright (C) 2022 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15
16 #include "confui_sign_server.h"
17
18 #include <android-base/logging.h>
19
20 #include "host/commands/secure_env/primary_key_builder.h"
21 #include "host/commands/secure_env/tpm_hmac.h"
22 #include "host/libs/config/cuttlefish_config.h"
23 #include "tpm_keymaster_context.h"
24
25 namespace {
26
27 // Defined in
28 // hardware/interfaces/confirmationui/1.0/IConfirmationResultCallback.hal
29 constexpr const char kConfirmationTokenMessageTag[] = "confirmation token";
30
31 } // namespace
32
33 namespace cuttlefish {
ConfUiSignServer(TpmResourceManager & tpm_resource_manager,SharedFD server_fd)34 ConfUiSignServer::ConfUiSignServer(TpmResourceManager& tpm_resource_manager,
35 SharedFD server_fd)
36 : tpm_resource_manager_(tpm_resource_manager), server_fd_(server_fd) {
37 auto config = cuttlefish::CuttlefishConfig::Get();
38 CHECK(config) << "Config must not be null";
39 auto instance = config->ForDefaultInstance();
40 server_socket_path_ = instance.PerInstanceInternalUdsPath("confui_sign.sock");
41 }
42
MainLoop()43 [[noreturn]] void ConfUiSignServer::MainLoop() {
44 while (true) {
45 if (!server_fd_->IsOpen()) {
46 server_fd_ = SharedFD::SocketLocalServer(server_socket_path_, false,
47 SOCK_STREAM, 0600);
48 }
49 auto accepted_socket_fd = SharedFD::Accept(*server_fd_);
50 if (!accepted_socket_fd->IsOpen()) {
51 LOG(ERROR) << "Confirmation UI host signing client socket is broken.";
52 continue;
53 }
54 ConfUiSignSender sign_sender(accepted_socket_fd);
55
56 // receive request
57 auto request_opt = sign_sender.Receive();
58 if (!request_opt) {
59 std::string error_category = (sign_sender.IsIoError() ? "IO" : "Logic");
60 LOG(ERROR) << "ReceiveRequest failed with " << error_category << " error";
61 continue;
62 }
63 auto request = request_opt.value();
64
65 // hmac over (prefix || data)
66 std::vector<std::uint8_t> data{std::begin(kConfirmationTokenMessageTag),
67 std::end(kConfirmationTokenMessageTag) - 1};
68
69 data.insert(data.end(), request.payload_.data(),
70 request.payload_.data() + request.payload_.size());
71 auto hmac = TpmHmacWithContext(tpm_resource_manager_, "confirmation_token",
72 data.data(), data.size());
73 if (!hmac) {
74 LOG(ERROR) << "Could not calculate confirmation token hmac";
75 sign_sender.Send(confui::SignMessageError::kUnknownError, {});
76 continue;
77 }
78 CHECK(hmac->size == keymaster::kConfirmationTokenSize)
79 << "Hmac size for confirmation UI must be "
80 << keymaster::kConfirmationTokenSize;
81
82 // send hmac
83 std::vector<std::uint8_t> hmac_buffer(hmac->buffer,
84 hmac->buffer + hmac->size);
85 if (!sign_sender.Send(confui::SignMessageError::kOk, hmac_buffer)) {
86 LOG(ERROR) << "Sending signature failed likely due to I/O error";
87 }
88 }
89 }
90 } // namespace cuttlefish
91