xref: /aosp_15_r20/hardware/interfaces/gatekeeper/aidl/software/GateKeeper.cpp (revision 4d7e907c777eeecc4c5bd7cf640a754fac206ff7)
1*4d7e907cSAndroid Build Coastguard Worker /*
2*4d7e907cSAndroid Build Coastguard Worker  * Copyright (C) 2016 The Android Open Source Project
3*4d7e907cSAndroid Build Coastguard Worker  *
4*4d7e907cSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*4d7e907cSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*4d7e907cSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*4d7e907cSAndroid Build Coastguard Worker  *
8*4d7e907cSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*4d7e907cSAndroid Build Coastguard Worker  *
10*4d7e907cSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*4d7e907cSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*4d7e907cSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*4d7e907cSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*4d7e907cSAndroid Build Coastguard Worker  * limitations under the License.
15*4d7e907cSAndroid Build Coastguard Worker  */
16*4d7e907cSAndroid Build Coastguard Worker #define LOG_TAG "android.hardware.gatekeeper-service.nonsecure"
17*4d7e907cSAndroid Build Coastguard Worker 
18*4d7e907cSAndroid Build Coastguard Worker #include <endian.h>
19*4d7e907cSAndroid Build Coastguard Worker 
20*4d7e907cSAndroid Build Coastguard Worker #include <android-base/logging.h>
21*4d7e907cSAndroid Build Coastguard Worker 
22*4d7e907cSAndroid Build Coastguard Worker #include "GateKeeper.h"
23*4d7e907cSAndroid Build Coastguard Worker 
24*4d7e907cSAndroid Build Coastguard Worker using ::gatekeeper::EnrollRequest;
25*4d7e907cSAndroid Build Coastguard Worker using ::gatekeeper::EnrollResponse;
26*4d7e907cSAndroid Build Coastguard Worker using ::gatekeeper::ERROR_NONE;
27*4d7e907cSAndroid Build Coastguard Worker using ::gatekeeper::ERROR_RETRY;
28*4d7e907cSAndroid Build Coastguard Worker using ::gatekeeper::SizedBuffer;
29*4d7e907cSAndroid Build Coastguard Worker using ::gatekeeper::VerifyRequest;
30*4d7e907cSAndroid Build Coastguard Worker using ::gatekeeper::VerifyResponse;
31*4d7e907cSAndroid Build Coastguard Worker 
32*4d7e907cSAndroid Build Coastguard Worker namespace aidl::android::hardware::gatekeeper {
33*4d7e907cSAndroid Build Coastguard Worker 
vec2sized_buffer(const std::vector<uint8_t> & vec)34*4d7e907cSAndroid Build Coastguard Worker SizedBuffer vec2sized_buffer(const std::vector<uint8_t>& vec) {
35*4d7e907cSAndroid Build Coastguard Worker     if (vec.size() == 0 || vec.size() > std::numeric_limits<uint32_t>::max()) {
36*4d7e907cSAndroid Build Coastguard Worker         return {};
37*4d7e907cSAndroid Build Coastguard Worker     }
38*4d7e907cSAndroid Build Coastguard Worker     auto unused = new uint8_t[vec.size()];
39*4d7e907cSAndroid Build Coastguard Worker     std::copy(vec.begin(), vec.end(), unused);
40*4d7e907cSAndroid Build Coastguard Worker     return {unused, static_cast<uint32_t>(vec.size())};
41*4d7e907cSAndroid Build Coastguard Worker }
42*4d7e907cSAndroid Build Coastguard Worker 
sizedBuffer2AidlHWToken(SizedBuffer & buffer,android::hardware::security::keymint::HardwareAuthToken * aidlToken)43*4d7e907cSAndroid Build Coastguard Worker void sizedBuffer2AidlHWToken(SizedBuffer& buffer,
44*4d7e907cSAndroid Build Coastguard Worker                              android::hardware::security::keymint::HardwareAuthToken* aidlToken) {
45*4d7e907cSAndroid Build Coastguard Worker     const hw_auth_token_t* authToken =
46*4d7e907cSAndroid Build Coastguard Worker             reinterpret_cast<const hw_auth_token_t*>(buffer.Data<uint8_t>());
47*4d7e907cSAndroid Build Coastguard Worker     aidlToken->challenge = authToken->challenge;
48*4d7e907cSAndroid Build Coastguard Worker     aidlToken->userId = authToken->user_id;
49*4d7e907cSAndroid Build Coastguard Worker     aidlToken->authenticatorId = authToken->authenticator_id;
50*4d7e907cSAndroid Build Coastguard Worker     // these are in network order: translate to host
51*4d7e907cSAndroid Build Coastguard Worker     aidlToken->authenticatorType =
52*4d7e907cSAndroid Build Coastguard Worker             static_cast<android::hardware::security::keymint::HardwareAuthenticatorType>(
53*4d7e907cSAndroid Build Coastguard Worker                     be32toh(authToken->authenticator_type));
54*4d7e907cSAndroid Build Coastguard Worker     aidlToken->timestamp.milliSeconds = be64toh(authToken->timestamp);
55*4d7e907cSAndroid Build Coastguard Worker     aidlToken->mac.insert(aidlToken->mac.begin(), std::begin(authToken->hmac),
56*4d7e907cSAndroid Build Coastguard Worker                           std::end(authToken->hmac));
57*4d7e907cSAndroid Build Coastguard Worker }
58*4d7e907cSAndroid Build Coastguard Worker 
SoftGateKeeperDevice(::gatekeeper::SoftGateKeeper & impl)59*4d7e907cSAndroid Build Coastguard Worker SoftGateKeeperDevice::SoftGateKeeperDevice(::gatekeeper::SoftGateKeeper& impl) : impl_(impl) {}
60*4d7e907cSAndroid Build Coastguard Worker 
enroll(int32_t uid,const std::vector<uint8_t> & currentPasswordHandle,const std::vector<uint8_t> & currentPassword,const std::vector<uint8_t> & desiredPassword,GatekeeperEnrollResponse * rsp)61*4d7e907cSAndroid Build Coastguard Worker ::ndk::ScopedAStatus SoftGateKeeperDevice::enroll(int32_t uid,
62*4d7e907cSAndroid Build Coastguard Worker                                                   const std::vector<uint8_t>& currentPasswordHandle,
63*4d7e907cSAndroid Build Coastguard Worker                                                   const std::vector<uint8_t>& currentPassword,
64*4d7e907cSAndroid Build Coastguard Worker                                                   const std::vector<uint8_t>& desiredPassword,
65*4d7e907cSAndroid Build Coastguard Worker                                                   GatekeeperEnrollResponse* rsp) {
66*4d7e907cSAndroid Build Coastguard Worker     if (desiredPassword.size() == 0) {
67*4d7e907cSAndroid Build Coastguard Worker         LOG(ERROR) << "Desired password size is 0";
68*4d7e907cSAndroid Build Coastguard Worker         return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(ERROR_GENERAL_FAILURE));
69*4d7e907cSAndroid Build Coastguard Worker     }
70*4d7e907cSAndroid Build Coastguard Worker 
71*4d7e907cSAndroid Build Coastguard Worker     if (currentPasswordHandle.size() > 0) {
72*4d7e907cSAndroid Build Coastguard Worker         if (currentPasswordHandle.size() != sizeof(::gatekeeper::password_handle_t)) {
73*4d7e907cSAndroid Build Coastguard Worker             LOG(ERROR) << "Password handle has wrong length";
74*4d7e907cSAndroid Build Coastguard Worker             return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(ERROR_GENERAL_FAILURE));
75*4d7e907cSAndroid Build Coastguard Worker         }
76*4d7e907cSAndroid Build Coastguard Worker     }
77*4d7e907cSAndroid Build Coastguard Worker 
78*4d7e907cSAndroid Build Coastguard Worker     EnrollRequest request(uid, vec2sized_buffer(currentPasswordHandle),
79*4d7e907cSAndroid Build Coastguard Worker                           vec2sized_buffer(desiredPassword), vec2sized_buffer(currentPassword));
80*4d7e907cSAndroid Build Coastguard Worker     EnrollResponse response;
81*4d7e907cSAndroid Build Coastguard Worker     impl_.Enroll(request, &response);
82*4d7e907cSAndroid Build Coastguard Worker     if (response.error == ERROR_RETRY) {
83*4d7e907cSAndroid Build Coastguard Worker         LOG(ERROR) << "Enroll response has a retry error";
84*4d7e907cSAndroid Build Coastguard Worker         *rsp = {ERROR_RETRY_TIMEOUT, static_cast<int32_t>(response.retry_timeout), 0, {}};
85*4d7e907cSAndroid Build Coastguard Worker         return ndk::ScopedAStatus::ok();
86*4d7e907cSAndroid Build Coastguard Worker     } else if (response.error != ERROR_NONE) {
87*4d7e907cSAndroid Build Coastguard Worker         LOG(ERROR) << "Enroll response has an error: " << response.error;
88*4d7e907cSAndroid Build Coastguard Worker         return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(ERROR_GENERAL_FAILURE));
89*4d7e907cSAndroid Build Coastguard Worker     } else {
90*4d7e907cSAndroid Build Coastguard Worker         const ::gatekeeper::password_handle_t* password_handle =
91*4d7e907cSAndroid Build Coastguard Worker                 response.enrolled_password_handle.Data<::gatekeeper::password_handle_t>();
92*4d7e907cSAndroid Build Coastguard Worker         *rsp = {STATUS_OK,
93*4d7e907cSAndroid Build Coastguard Worker                 0,
94*4d7e907cSAndroid Build Coastguard Worker                 static_cast<int64_t>(password_handle->user_id),
95*4d7e907cSAndroid Build Coastguard Worker                 {response.enrolled_password_handle.Data<uint8_t>(),
96*4d7e907cSAndroid Build Coastguard Worker                  (response.enrolled_password_handle.Data<uint8_t>() +
97*4d7e907cSAndroid Build Coastguard Worker                   response.enrolled_password_handle.size())}};
98*4d7e907cSAndroid Build Coastguard Worker     }
99*4d7e907cSAndroid Build Coastguard Worker     return ndk::ScopedAStatus::ok();
100*4d7e907cSAndroid Build Coastguard Worker }
101*4d7e907cSAndroid Build Coastguard Worker 
verify(int32_t uid,int64_t challenge,const std::vector<uint8_t> & enrolledPasswordHandle,const std::vector<uint8_t> & providedPassword,GatekeeperVerifyResponse * rsp)102*4d7e907cSAndroid Build Coastguard Worker ::ndk::ScopedAStatus SoftGateKeeperDevice::verify(
103*4d7e907cSAndroid Build Coastguard Worker         int32_t uid, int64_t challenge, const std::vector<uint8_t>& enrolledPasswordHandle,
104*4d7e907cSAndroid Build Coastguard Worker         const std::vector<uint8_t>& providedPassword, GatekeeperVerifyResponse* rsp) {
105*4d7e907cSAndroid Build Coastguard Worker     if (enrolledPasswordHandle.size() == 0) {
106*4d7e907cSAndroid Build Coastguard Worker         LOG(ERROR) << "Enrolled password size is 0";
107*4d7e907cSAndroid Build Coastguard Worker         return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(ERROR_GENERAL_FAILURE));
108*4d7e907cSAndroid Build Coastguard Worker     }
109*4d7e907cSAndroid Build Coastguard Worker 
110*4d7e907cSAndroid Build Coastguard Worker     if (enrolledPasswordHandle.size() > 0) {
111*4d7e907cSAndroid Build Coastguard Worker         if (enrolledPasswordHandle.size() != sizeof(::gatekeeper::password_handle_t)) {
112*4d7e907cSAndroid Build Coastguard Worker             LOG(ERROR) << "Password handle has wrong length";
113*4d7e907cSAndroid Build Coastguard Worker             return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(ERROR_GENERAL_FAILURE));
114*4d7e907cSAndroid Build Coastguard Worker         }
115*4d7e907cSAndroid Build Coastguard Worker     }
116*4d7e907cSAndroid Build Coastguard Worker 
117*4d7e907cSAndroid Build Coastguard Worker     VerifyRequest request(uid, challenge, vec2sized_buffer(enrolledPasswordHandle),
118*4d7e907cSAndroid Build Coastguard Worker                           vec2sized_buffer(providedPassword));
119*4d7e907cSAndroid Build Coastguard Worker     VerifyResponse response;
120*4d7e907cSAndroid Build Coastguard Worker     impl_.Verify(request, &response);
121*4d7e907cSAndroid Build Coastguard Worker 
122*4d7e907cSAndroid Build Coastguard Worker     if (response.error == ERROR_RETRY) {
123*4d7e907cSAndroid Build Coastguard Worker         LOG(ERROR) << "Verify request response gave retry error";
124*4d7e907cSAndroid Build Coastguard Worker         *rsp = {ERROR_RETRY_TIMEOUT, static_cast<int32_t>(response.retry_timeout), {}};
125*4d7e907cSAndroid Build Coastguard Worker         return ndk::ScopedAStatus::ok();
126*4d7e907cSAndroid Build Coastguard Worker     } else if (response.error != ERROR_NONE) {
127*4d7e907cSAndroid Build Coastguard Worker         LOG(ERROR) << "Verify request response gave error: " << response.error;
128*4d7e907cSAndroid Build Coastguard Worker         return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(ERROR_GENERAL_FAILURE));
129*4d7e907cSAndroid Build Coastguard Worker     } else {
130*4d7e907cSAndroid Build Coastguard Worker         // On Success, return GatekeeperVerifyResponse with Success Status, timeout{0} and
131*4d7e907cSAndroid Build Coastguard Worker         // valid HardwareAuthToken.
132*4d7e907cSAndroid Build Coastguard Worker         *rsp = {response.request_reenroll ? STATUS_REENROLL : STATUS_OK, 0, {}};
133*4d7e907cSAndroid Build Coastguard Worker         // Convert the hw_auth_token_t to HardwareAuthToken in the response.
134*4d7e907cSAndroid Build Coastguard Worker         sizedBuffer2AidlHWToken(response.auth_token, &rsp->hardwareAuthToken);
135*4d7e907cSAndroid Build Coastguard Worker     }
136*4d7e907cSAndroid Build Coastguard Worker     return ndk::ScopedAStatus::ok();
137*4d7e907cSAndroid Build Coastguard Worker }
138*4d7e907cSAndroid Build Coastguard Worker 
deleteUser(int32_t)139*4d7e907cSAndroid Build Coastguard Worker ::ndk::ScopedAStatus SoftGateKeeperDevice::deleteUser(int32_t /*uid*/) {
140*4d7e907cSAndroid Build Coastguard Worker     LOG(ERROR) << "deleteUser is unimplemented";
141*4d7e907cSAndroid Build Coastguard Worker     return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(ERROR_NOT_IMPLEMENTED));
142*4d7e907cSAndroid Build Coastguard Worker }
143*4d7e907cSAndroid Build Coastguard Worker 
deleteAllUsers()144*4d7e907cSAndroid Build Coastguard Worker ::ndk::ScopedAStatus SoftGateKeeperDevice::deleteAllUsers() {
145*4d7e907cSAndroid Build Coastguard Worker     LOG(ERROR) << "deleteAllUsers is unimplemented";
146*4d7e907cSAndroid Build Coastguard Worker     return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(ERROR_NOT_IMPLEMENTED));
147*4d7e907cSAndroid Build Coastguard Worker }
148*4d7e907cSAndroid Build Coastguard Worker 
149*4d7e907cSAndroid Build Coastguard Worker }  // namespace aidl::android::hardware::gatekeeper
150