1 /*
2 * Copyright 2020 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
17 #include "common/libs/security/keymaster_channel_windows.h"
18
19 #include <windows.h>
20
21 #include <errhandlingapi.h>
22 #include <fileapi.h>
23 #include <handleapi.h>
24 #include <namedpipeapi.h>
25 #include <chrono>
26 #include <cstdlib>
27 #include <thread>
28
29 #include <android-base/logging.h>
30 #include <keymaster/android_keymaster_utils.h>
31
32 namespace cuttlefish {
33 using keymaster::keymaster_message;
34
Create(HANDLE pipe_handle)35 std::unique_ptr<KeymasterWindowsChannel> KeymasterWindowsChannel::Create(
36 HANDLE pipe_handle) {
37 auto keymaster_channel =
38 std::unique_ptr<KeymasterWindowsChannel>(new KeymasterWindowsChannel());
39 if (!keymaster_channel->WaitForConnection(pipe_handle)) {
40 return nullptr;
41 }
42
43 return keymaster_channel;
44 }
45
WaitForConnection(HANDLE pipe_handle)46 bool KeymasterWindowsChannel::WaitForConnection(HANDLE pipe_handle) {
47 assert(pipe_handle_ == NULL);
48 pipe_handle_ = pipe_handle;
49
50 DWORD flags;
51 if (GetNamedPipeInfo(pipe_handle_,
52 /*lpFlags= */ &flags,
53 /*lpOutBufferSize= */ NULL,
54 /* lpInBufferSize= */ NULL,
55 /* lpMaxInstances= */ NULL) == 0) {
56 LOG(ERROR)
57 << "Could not query Keymaster named pipe handle info. Got error code "
58 << GetLastError();
59 return false;
60 }
61
62 if ((flags & PIPE_SERVER_END) == 0) {
63 LOG(ERROR) << "Keymaster handle is not the server end of a named pipe!";
64 return false;
65 }
66
67 // Create the event object
68 HANDLE event_handle =
69 CreateEventA(/* lpEventAttributes= */ NULL, /* bManualReset= */ true,
70 /* bInitialState= */ 0, /* lpName= */ NULL);
71 if (event_handle == NULL) {
72 LOG(ERROR)
73 << "Error: Could not create keymaster event object. Got error code "
74 << GetLastError();
75 return false;
76 }
77 pipe_overlapped_.hEvent = event_handle;
78
79 // Wait for client to connect to the pipe
80 ConnectNamedPipe(pipe_handle_, &pipe_overlapped_);
81 LOG(INFO) << "Listening to existing keymaster pipe handle.";
82
83 if (WaitForSingleObject(pipe_overlapped_.hEvent, INFINITE) != WAIT_OBJECT_0) {
84 LOG(ERROR) << "Could not wait for Keymaster pipe's overlapped to be "
85 "signalled. Got Windows error code "
86 << GetLastError();
87 return false;
88 }
89 if (!ResetEvent(pipe_overlapped_.hEvent)) {
90 LOG(ERROR) << "Could not reset Keymaster pipe's overlapped. Got Windows "
91 "error code "
92 << GetLastError();
93 return false;
94 }
95 return true;
96 }
97
~KeymasterWindowsChannel()98 KeymasterWindowsChannel::~KeymasterWindowsChannel() {
99 if (pipe_handle_) {
100 CloseHandle(pipe_handle_);
101 }
102
103 if (pipe_overlapped_.hEvent) {
104 CloseHandle(pipe_overlapped_.hEvent);
105 }
106 }
107
SendRequest(AndroidKeymasterCommand command,const keymaster::Serializable & message)108 bool KeymasterWindowsChannel::SendRequest(
109 AndroidKeymasterCommand command, const keymaster::Serializable& message) {
110 return SendMessage(command, false, message);
111 }
112
SendResponse(AndroidKeymasterCommand command,const keymaster::Serializable & message)113 bool KeymasterWindowsChannel::SendResponse(
114 AndroidKeymasterCommand command, const keymaster::Serializable& message) {
115 return SendMessage(command, true, message);
116 }
117
SendMessage(AndroidKeymasterCommand command,bool is_response,const keymaster::Serializable & message)118 bool KeymasterWindowsChannel::SendMessage(
119 AndroidKeymasterCommand command, bool is_response,
120 const keymaster::Serializable& message) {
121 auto payload_size = message.SerializedSize();
122 if (payload_size > 1024 * 1024) {
123 LOG(WARNING) << "Sending large message with id: " << command << " and size "
124 << payload_size;
125 }
126
127 auto to_send = CreateKeymasterMessage(command, is_response, payload_size);
128 message.Serialize(to_send->payload, to_send->payload + payload_size);
129 auto write_size = payload_size + sizeof(keymaster_message);
130 auto to_send_bytes = reinterpret_cast<const char*>(to_send.get());
131 if (!WriteFile(pipe_handle_, to_send_bytes, write_size, NULL,
132 &pipe_overlapped_) &&
133 GetLastError() != ERROR_IO_PENDING) {
134 LOG(ERROR) << "Could not write Keymaster Message. Got Windows error code "
135 << GetLastError();
136 return false;
137 }
138
139 // Vsock pipes are overlapped (asynchronous) and we need to wait for the
140 // overlapped event to be signaled.
141 // https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-waitforsingleobject#return-value
142 if (WaitForSingleObject(pipe_overlapped_.hEvent, INFINITE) != WAIT_OBJECT_0) {
143 LOG(ERROR) << "Could not wait for Keymaster pipe's overlapped to be "
144 "signalled. Got Windows error code "
145 << GetLastError();
146 return false;
147 }
148 if (!ResetEvent(pipe_overlapped_.hEvent)) {
149 LOG(ERROR) << "Could not reset Keymaster pipe's overlapped. Got Windows "
150 "error code "
151 << GetLastError();
152 return false;
153 }
154 return true;
155 }
156
ReadFromPipe(LPVOID buffer,DWORD size)157 bool KeymasterWindowsChannel::ReadFromPipe(LPVOID buffer, DWORD size) {
158 if (ReadFile(pipe_handle_, buffer, size, NULL, &pipe_overlapped_) == FALSE) {
159 if (GetLastError() == ERROR_BROKEN_PIPE) {
160 LOG(INFO) << "Keymaster pipe was closed.";
161 return false;
162 } else if (GetLastError() != ERROR_IO_PENDING) {
163 LOG(ERROR) << "Could not read Keymaster message. Got Windows error code "
164 << GetLastError();
165 return false;
166 }
167
168 // Wait for the asynchronous read to finish.
169 DWORD unused_bytes_read;
170 if (GetOverlappedResult(pipe_handle_, &pipe_overlapped_, &unused_bytes_read,
171 /*bWait=*/TRUE) == FALSE) {
172 if (GetLastError() == ERROR_BROKEN_PIPE) {
173 LOG(INFO) << "Keymaster pipe was closed.";
174 return false;
175 }
176
177 LOG(ERROR) << "Error receiving Keymaster data. Got Windows error code "
178 << GetLastError();
179 return false;
180 }
181 }
182
183 if (ResetEvent(pipe_overlapped_.hEvent) == 0) {
184 LOG(ERROR) << "Error calling ResetEvent for Keymaster data. Got "
185 "Windows error code "
186 << GetLastError();
187
188 return false;
189 }
190
191 return true;
192 }
193
ReceiveMessage()194 ManagedKeymasterMessage KeymasterWindowsChannel::ReceiveMessage() {
195 struct keymaster_message message_header;
196 if (!ReadFromPipe(&message_header, sizeof(message_header))) {
197 return {};
198 }
199
200 if (message_header.payload_size > 1024 * 1024) {
201 LOG(WARNING) << "Received large message with id: " << message_header.cmd
202 << " and size " << message_header.payload_size;
203 }
204
205 auto message =
206 CreateKeymasterMessage(message_header.cmd, message_header.is_response,
207 message_header.payload_size);
208 auto message_bytes = reinterpret_cast<char*>(message->payload);
209
210 if (!ReadFromPipe(message_bytes, message->payload_size)) {
211 return {};
212 }
213
214 return message;
215 }
216
217 } // namespace cuttlefish