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