1 /*
2  * Copyright (C) 2021 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 <chre.h>
18 
19 #include <pb_decode.h>
20 #include <cinttypes>
21 
22 #include "chre/util/nanoapp/log.h"
23 #include "chre/util/time.h"
24 #include "permission_test.nanopb.h"
25 #include "send_message.h"
26 
27 #define LOG_TAG "[PermissionTest]"
28 
29 /**
30  * This nanoapp is compiled with the ability to refer to permission gated APIs
31  * but doesn't actually declare permissions to use them. Its purpose is to
32  * validate the permission gated APIs always return false for any of its
33  * requests to ensure CHRE implementations are validating nanoapp permissions
34  * prior to accepting a nanoapp request.
35  */
36 
37 namespace chre {
38 namespace {
39 
40 constexpr Nanoseconds kGnssMinInterval = Seconds(1);
41 
checkAudioApis(uint32_t hostEndpointId)42 void checkAudioApis(uint32_t hostEndpointId) {
43   struct chreAudioSource audioSource;
44   for (uint32_t i = 0; chreAudioGetSource(i, &audioSource); i++) {
45     if (chreAudioConfigureSource(i, true /* enable */,
46                                  audioSource.minBufferDuration,
47                                  audioSource.minBufferDuration)) {
48       test_shared::sendTestResultWithMsgToHost(
49           hostEndpointId, permission_test_MessageType_TEST_RESULT,
50           false /* success */, "Configured audio without audio permission");
51     }
52 
53     // TODO(b/174590023): Check chreAudioGetStatus once it's supported by our
54     // CHRE versions.
55   }
56 }
57 
checkGnssApis(uint32_t hostEndpointId)58 void checkGnssApis(uint32_t hostEndpointId) {
59   if (chreGnssLocationSessionStartAsync(kGnssMinInterval.toRawNanoseconds(),
60                                         kGnssMinInterval.toRawNanoseconds(),
61                                         nullptr /* cookie */)) {
62     test_shared::sendTestResultWithMsgToHost(
63         hostEndpointId, permission_test_MessageType_TEST_RESULT,
64         false /* success */,
65         "Requested GNSS location without the GNSS permission");
66   }
67 
68   if (chreGnssMeasurementSessionStartAsync(kGnssMinInterval.toRawNanoseconds(),
69                                            nullptr /* cookie */)) {
70     test_shared::sendTestResultWithMsgToHost(
71         hostEndpointId, permission_test_MessageType_TEST_RESULT,
72         false /* success */,
73         "Requested GNSS measurements without the GNSS permission");
74   }
75 
76   if (chreGnssConfigurePassiveLocationListener(true /* enable */)) {
77     test_shared::sendTestResultWithMsgToHost(
78         hostEndpointId, permission_test_MessageType_TEST_RESULT,
79         false /* success */,
80         "Requested GNSS passive locations without the GNSS permission");
81   }
82 }
83 
checkWifiApis(uint32_t hostEndpointId)84 void checkWifiApis(uint32_t hostEndpointId) {
85   if (chreWifiConfigureScanMonitorAsync(true /* enable */,
86                                         nullptr /* cookie */)) {
87     test_shared::sendTestResultWithMsgToHost(
88         hostEndpointId, permission_test_MessageType_TEST_RESULT,
89         false /* success */,
90         "Requested WiFi scan monitor without WiFi permission");
91   }
92 
93   if (chreWifiRequestScanAsyncDefault(nullptr /* cookie */)) {
94     test_shared::sendTestResultWithMsgToHost(
95         hostEndpointId, permission_test_MessageType_TEST_RESULT,
96         false /* success */, "Requested WiFi scan without WiFi permission");
97   }
98 
99   // RTT ranging not included in WiFi test because it requires a valid AP to
100   // request which can't be obtained due to invalid permissions.
101 }
102 
checkWwanApis(uint32_t hostEndpointId)103 void checkWwanApis(uint32_t hostEndpointId) {
104   if (chreWwanGetCellInfoAsync(nullptr /* cookie */)) {
105     test_shared::sendTestResultWithMsgToHost(
106         hostEndpointId, permission_test_MessageType_TEST_RESULT,
107         false /* success */, "Requested cell info without WWAN permission");
108   }
109 }
110 
111 // Call APIs that require permissions and verify that they all refuse requests
112 // from this nanoapp since it has no permissions.
checkPermissionGatedApis(uint32_t hostEndpointId)113 void checkPermissionGatedApis(uint32_t hostEndpointId) {
114   checkAudioApis(hostEndpointId);
115   checkGnssApis(hostEndpointId);
116   checkWifiApis(hostEndpointId);
117   checkWwanApis(hostEndpointId);
118 }
119 
handleMessageFromHost(uint32_t senderInstanceId,const chreMessageFromHostData * hostData)120 void handleMessageFromHost(uint32_t senderInstanceId,
121                            const chreMessageFromHostData *hostData) {
122   bool success = false;
123   uint32_t messageType = hostData->messageType;
124   if (senderInstanceId != CHRE_INSTANCE_ID) {
125     LOGE("Incorrect sender instance id: %" PRIu32, senderInstanceId);
126   } else if (messageType != permission_test_MessageType_TEST_COMMAND) {
127     LOGE("Invalid message type %" PRIu32, messageType);
128   } else {
129     // Method will abort if any failures are encountered.
130     checkPermissionGatedApis(hostData->hostEndpoint);
131     success = true;
132   }
133 
134   test_shared::sendTestResultWithMsgToHost(
135       hostData->hostEndpoint,
136       permission_test_MessageType_TEST_RESULT /* messageType */, success,
137       nullptr /* errMessage */);
138 }
139 
140 }  // anonymous namespace
141 
nanoappHandleEvent(uint32_t senderInstanceId,uint16_t eventType,const void * eventData)142 extern "C" void nanoappHandleEvent(uint32_t senderInstanceId,
143                                    uint16_t eventType, const void *eventData) {
144   if (eventType == CHRE_EVENT_MESSAGE_FROM_HOST) {
145     handleMessageFromHost(
146         senderInstanceId,
147         static_cast<const chreMessageFromHostData *>(eventData));
148   } else {
149     LOGW("Got unknown event type from senderInstanceId %" PRIu32
150          " and with eventType %" PRIu16,
151          senderInstanceId, eventType);
152   }
153 }
154 
nanoappStart(void)155 extern "C" bool nanoappStart(void) {
156   return true;
157 }
158 
nanoappEnd(void)159 extern "C" void nanoappEnd(void) {}
160 
161 }  // namespace chre
162