1 //
2 // Copyright (C) 2023 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 "host/commands/secure_env/oemlock/oemlock_responder.h"
17 
18 #include "common/libs/security/oemlock.h"
19 
20 namespace cuttlefish {
21 namespace oemlock {
22 
OemLockResponder(transport::Channel & channel,OemLock & oemlock,std::timed_mutex & lock)23 OemLockResponder::OemLockResponder(transport::Channel& channel,
24                                    OemLock& oemlock, std::timed_mutex& lock)
25     : channel_(channel), oemlock_(oemlock), lock_(lock) {}
26 
ProcessMessage()27 Result<void> OemLockResponder::ProcessMessage() {
28   CF_EXPECT(channel_.WaitForMessage(), "Could not receive message");
29 
30   {
31     std::lock_guard lock(lock_);
32     LOG(DEBUG) << "Receiving oemlock command";
33     auto request =
34         CF_EXPECT(channel_.ReceiveMessage(), "Could not receive message");
35 
36     bool result = false;
37     switch (secure_env::OemLockField(request->command)) {
38       case secure_env::OemLockField::ALLOWED_BY_CARRIER: {
39         if (request->payload_size == 0) {
40           result = CF_EXPECT(oemlock_.IsOemUnlockAllowedByCarrier());
41         } else if (request->payload_size == sizeof(bool)) {
42           result = *reinterpret_cast<bool*>(request->payload);
43           CF_EXPECT(oemlock_.SetOemUnlockAllowedByCarrier(result));
44         }
45         break;
46       }
47 
48       case secure_env::OemLockField::ALLOWED_BY_DEVICE: {
49         if (request->payload_size == 0) {
50           result = CF_EXPECT(oemlock_.IsOemUnlockAllowedByDevice());
51         } else if (request->payload_size == sizeof(bool)) {
52           result = *reinterpret_cast<bool*>(request->payload);
53           CF_EXPECT(oemlock_.SetOemUnlockAllowedByDevice(result));
54         }
55         break;
56       }
57 
58       case secure_env::OemLockField::ALLOWED: {
59         if (request->payload_size == 0) {
60           result = CF_EXPECT(oemlock_.IsOemUnlockAllowed());
61         }
62         break;
63       }
64 
65       case secure_env::OemLockField::LOCKED: {
66         if (request->payload_size == 0) {
67           result = CF_EXPECT(oemlock_.IsOemLocked());
68         } else if (request->payload_size == sizeof(bool)) {
69           result = *reinterpret_cast<bool*>(request->payload);
70           CF_EXPECT(oemlock_.SetOemLocked(result));
71         }
72         break;
73       }
74 
75       default:
76         return CF_ERR("Unrecognized message id "
77                       << reinterpret_cast<uint32_t>(request->command));
78     }
79 
80     auto message =
81         CF_EXPECT(transport::CreateMessage(request->command, sizeof(bool)),
82                   "Failed to allocate message for oemlock response");
83     memcpy(message->payload, &result, sizeof(bool));
84     LOG(DEBUG) << "Sending oemlock response";
85     CF_EXPECT(channel_.SendResponse(*message),
86               "Could not answer to "
87                   << reinterpret_cast<uint32_t>(request->command)
88                   << " request");
89   }
90 
91   return {};
92 }
93 
94 }  // namespace oemlock
95 }  // namespace cuttlefish
96