1 /*
2 * Copyright (C) 2025 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 #define FAILURE_DEBUG_PREFIX "RadioSim"
18
19 #include <charconv>
20 #include <format>
21 #include <tuple>
22 #include <vector>
23
24 #include "RadioSim.h"
25
26 #include "atCmds.h"
27 #include "debug.h"
28 #include "hexbin.h"
29 #include "makeRadioResponseInfo.h"
30
31 namespace aidl {
32 namespace android {
33 namespace hardware {
34 namespace radio {
35 namespace implementation {
36 namespace {
37 using namespace std::literals;
38
39 enum class AuthContext {
40 SIM = 128,
41 AKA = 129,
42 };
43
44 enum class StkCmdType {
45 RUN_AT = 0x34,
46 SEND_DTMF = 0x14,
47 SEND_SMS = 0x13,
48 SEND_SS = 0x11,
49 SEND_USSD = 0x12,
50 PLAY_TONE = 0x20,
51 OPEN_CHANNEL = 0x40,
52 CLOSE_CHANNEL = 0x41,
53 RECEIVE_DATA = 0x42,
54 SEND_DATA = 0x43,
55 GET_CHANNEL_STATUS = 0x44,
56 REFRESH = 0x01,
57 };
58
59 #define USIM_DATA_OFFSET_2 2
60 #define USIM_DATA_OFFSET_3 3
61 #define USIM_RESPONSE_DATA_FILE_RECORD_LEN_1 6
62 #define USIM_RESPONSE_DATA_FILE_RECORD_LEN_2 7
63 #define USIM_TYPE_FILE_DES_LEN 5
64
65 #define USIM_RESPONSE_DATA_FILE_DES_FLAG 2
66 #define USIM_RESPONSE_DATA_FILE_DES_LEN_FLAG 3
67
68 #define USIM_FILE_DES_TAG 0x82
69 #define USIM_FILE_SIZE_TAG 0x80
70
71
72 #define SIM_RESPONSE_EF_SIZE 15
73 #define SIM_RESPONSE_DATA_FILE_SIZE_1 2
74 #define SIM_RESPONSE_DATA_FILE_SIZE_2 3
75 #define SIM_RESPONSE_DATA_FILE_TYPE 6
76 #define SIM_RESPONSE_DATA_STRUCTURE 13
77 #define SIM_RESPONSE_DATA_RECORD_LENGTH 14
78 #define SIM_TYPE_EF 4
79
80 enum class UsimEfType {
81 TRANSPARENT = 1,
82 LINEAR_FIXED = 2,
83 CYCLIC = 6,
84 };
85
86 // 62 17 82 02 41 2183022FE28A01058B032F06038002000A880110
convertUsimToSim(const std::vector<uint8_t> & bytesUSIM,std::string * hexSIM)87 bool convertUsimToSim(const std::vector<uint8_t>& bytesUSIM, std::string* hexSIM) {
88 const size_t sz = bytesUSIM.size();
89 size_t i = 0;
90
91 size_t desIndex;
92 while (true) {
93 if (bytesUSIM[i] == USIM_FILE_DES_TAG) {
94 desIndex = i;
95 break;
96 } else {
97 ++i;
98 if (i >= sz) {
99 return false;
100 }
101 }
102 }
103
104 size_t sizeIndex;
105 while (true) {
106 if (bytesUSIM[i] == USIM_FILE_SIZE_TAG) {
107 sizeIndex = i;
108 break;
109 } else {
110 i += bytesUSIM[i + 1] + 2;
111 if (i >= sz) {
112 return FAILURE(false);
113 }
114 }
115 }
116
117 uint8_t bytesSIM[SIM_RESPONSE_EF_SIZE] = {0};
118 switch (static_cast<UsimEfType>(bytesUSIM[desIndex + USIM_RESPONSE_DATA_FILE_DES_FLAG] & 0x07)) {
119 case UsimEfType::TRANSPARENT:
120 bytesSIM[SIM_RESPONSE_DATA_STRUCTURE] = 0;
121 break;
122
123 case UsimEfType::LINEAR_FIXED:
124 if (USIM_FILE_DES_TAG != bytesUSIM[USIM_RESPONSE_DATA_FILE_DES_FLAG]) {
125 return FAILURE(false);
126 }
127 if (USIM_TYPE_FILE_DES_LEN != bytesUSIM[USIM_RESPONSE_DATA_FILE_DES_LEN_FLAG]) {
128 return FAILURE(false);
129 }
130
131 bytesSIM[SIM_RESPONSE_DATA_STRUCTURE] = 1;
132 bytesSIM[SIM_RESPONSE_DATA_RECORD_LENGTH] =
133 //(byteUSIM[USIM_RESPONSE_DATA_FILE_RECORD_LEN_1] << 8) +
134 bytesUSIM[USIM_RESPONSE_DATA_FILE_RECORD_LEN_2];
135 break;
136
137 case UsimEfType::CYCLIC:
138 bytesSIM[SIM_RESPONSE_DATA_STRUCTURE] = 3;
139 bytesSIM[SIM_RESPONSE_DATA_RECORD_LENGTH] =
140 //(byteUSIM[USIM_RESPONSE_DATA_FILE_RECORD_LEN_1] << 8) +
141 bytesUSIM[USIM_RESPONSE_DATA_FILE_RECORD_LEN_2];
142 break;
143
144 default:
145 return false;
146 }
147
148 bytesSIM[SIM_RESPONSE_DATA_FILE_TYPE] = SIM_TYPE_EF;
149 bytesSIM[SIM_RESPONSE_DATA_FILE_SIZE_1] =
150 bytesUSIM[sizeIndex + USIM_DATA_OFFSET_2];
151 bytesSIM[SIM_RESPONSE_DATA_FILE_SIZE_2] =
152 bytesUSIM[sizeIndex + USIM_DATA_OFFSET_3];
153
154 *hexSIM = bin2hex(bytesSIM, sizeof(bytesSIM));
155 return true;
156 }
157
getRemainingRetries(const std::string_view pinType,const AtChannel::RequestPipe requestPipe,AtChannel::Conversation & atConversation)158 std::optional<int> getRemainingRetries(const std::string_view pinType,
159 const AtChannel::RequestPipe requestPipe,
160 AtChannel::Conversation& atConversation) {
161 using CPINR = AtResponse::CPINR;
162
163 AtResponsePtr response =
164 atConversation(requestPipe, std::format("AT+CPINR=\"{0:s}\"", pinType),
165 [](const AtResponse& response) -> bool {
166 return response.holds<CPINR>();
167 });
168 if (!response || response->isParseError()) {
169 return FAILURE(std::nullopt);
170 } else if (const CPINR* cpinr = response->get_if<CPINR>()) {
171 return cpinr->remainingRetryTimes;
172 } else {
173 response->unexpected(FAILURE_DEBUG_PREFIX, __func__);
174 }
175 }
176
enterOrChangeSimPinPuk(const bool change,const std::string_view oldPin,const std::string_view newPin,const std::string_view pinType,const AtChannel::RequestPipe requestPipe,AtChannel::Conversation & atConversation)177 std::pair<RadioError, int> enterOrChangeSimPinPuk(const bool change,
178 const std::string_view oldPin,
179 const std::string_view newPin,
180 const std::string_view pinType,
181 const AtChannel::RequestPipe requestPipe,
182 AtChannel::Conversation& atConversation) {
183 using CmeError = AtResponse::CmeError;
184
185 std::string request;
186 if (change) {
187 if (pinType.compare("SIM PIN2"sv) == 0) {
188 request = std::format("AT+CPWD=\"{0:s}\",\"{1:s}\",\"{2:s}\"",
189 "P2"sv, oldPin, newPin);
190 } else {
191 request = std::format("AT+CPIN={0:s},{1:s}", oldPin, newPin);
192 }
193 } else {
194 request = std::format("AT+CPIN={0:s}", oldPin);
195 }
196
197 AtResponsePtr response =
198 atConversation(requestPipe, request,
199 [](const AtResponse& response) -> bool {
200 return response.holds<CmeError>() || response.isOK();
201 });
202 if (!response || response->isParseError()) {
203 return {FAILURE(RadioError::INTERNAL_ERR), 0};
204 } else if (response->isOK()) {
205 return {RadioError::NONE, 0};
206 } else if (!response->get_if<CmeError>()) {
207 response->unexpected(FAILURE_DEBUG_PREFIX, __func__);
208 }
209
210 const std::optional<int> maybeRetries =
211 getRemainingRetries(pinType, requestPipe, atConversation);
212 if (maybeRetries) {
213 return {RadioError::PASSWORD_INCORRECT, maybeRetries.value()};
214 } else {
215 return {FAILURE(RadioError::INTERNAL_ERR), 0};
216 }
217 }
218
219 // authData64 = base64([randLen][...rand...][authLen][...auth...])
220 std::tuple<RadioError, std::vector<uint8_t>, std::vector<uint8_t>>
parseAuthData(const AuthContext authContext,const std::string_view authData64)221 parseAuthData(const AuthContext authContext, const std::string_view authData64) {
222 auto maybeAuthData = base64decode(authData64.data(), authData64.size());
223 if (!maybeAuthData) {
224 return {FAILURE(RadioError::INVALID_ARGUMENTS), {}, {}};
225 }
226
227 const std::vector<uint8_t> authData = std::move(maybeAuthData.value());
228 const size_t authDataSize = authData.size();
229 if (authDataSize == 0) {
230 return {FAILURE(RadioError::INVALID_ARGUMENTS), {}, {}};
231 }
232
233 const size_t randLen = authData[0];
234 if (authDataSize < (1U + randLen)) {
235 return {FAILURE(RadioError::INVALID_ARGUMENTS), {}, {}};
236 }
237
238 std::vector rand(&authData[1], &authData[1U + randLen]);
239 if (authContext == AuthContext::SIM) {
240 return {RadioError::NONE, std::move(rand), {}};
241 }
242
243 const size_t authLen = authData[1U + randLen];
244 if (authDataSize < (1U + randLen + 1U + authLen)) {
245 return {FAILURE(RadioError::INVALID_ARGUMENTS), {}, {}};
246 }
247
248 std::vector auth(&authData[1U + randLen + 1U],
249 &authData[1U + randLen + 1U + authLen]);
250 if (authContext == AuthContext::AKA) {
251 return {RadioError::NONE, std::move(rand), std::move(auth)};
252 }
253
254 return {FAILURE(RadioError::REQUEST_NOT_SUPPORTED), {}, {}};
255 }
256
getSelectResponse(const AtChannel::RequestPipe requestPipe,AtChannel::Conversation & atConversation,const int channel,const int p2)257 std::optional<std::vector<uint8_t>> getSelectResponse(const AtChannel::RequestPipe requestPipe,
258 AtChannel::Conversation& atConversation,
259 const int channel, const int p2) {
260 using CGLA = AtResponse::CGLA;
261 using CmeError = AtResponse::CmeError;
262
263 const std::string request =
264 std::format("AT+CGLA={0:d},14,00A400{1:02X}023F00", channel, p2);
265 AtResponsePtr response =
266 atConversation(requestPipe, request,
267 [](const AtResponse& response) -> bool {
268 return response.holds<CGLA>() || response.holds<CmeError>();
269 });
270 if (!response || response->isParseError()) {
271 return FAILURE(std::nullopt);
272 } else if (const CGLA* cgla = response->get_if<CGLA>()) {
273 if (cgla->response.size() < 4) {
274 return FAILURE(std::nullopt);
275 }
276
277 int sw12;
278 const size_t size4 = cgla->response.size() - 4;
279 if (1 != ::sscanf(&cgla->response[size4], "%04x", &sw12)) {
280 return FAILURE(std::nullopt);
281 }
282
283 if (sw12 != 0x9000) {
284 return FAILURE(std::nullopt);
285 }
286
287 std::vector<uint8_t> selectResponse;
288 if (!hex2bin(cgla->response, &selectResponse)) {
289 return FAILURE(std::nullopt);
290 }
291
292 return selectResponse;
293 } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
294 cmeError->getErrorAndLog(FAILURE_DEBUG_PREFIX, __func__, __LINE__);
295 return FAILURE(std::nullopt);
296 } else {
297 response->unexpected(FAILURE_DEBUG_PREFIX, __func__);
298 }
299 }
300
301 } // namespace
302
RadioSim(std::shared_ptr<AtChannel> atChannel)303 RadioSim::RadioSim(std::shared_ptr<AtChannel> atChannel) : mAtChannel(std::move(atChannel)) {
304 }
305
areUiccApplicationsEnabled(const int32_t serial)306 ScopedAStatus RadioSim::areUiccApplicationsEnabled(const int32_t serial) {
307 using modem::RadioState;
308
309 RadioState radioState;
310 {
311 std::lock_guard<std::mutex> lock(mMtx);
312 radioState = mRadioState;
313 }
314
315 const RadioError status = (radioState == RadioState::ON) ?
316 RadioError::NONE : RadioError::RADIO_NOT_AVAILABLE;
317
318 NOT_NULL(mRadioSimResponse)->areUiccApplicationsEnabledResponse(
319 makeRadioResponseInfo(serial, status), mUiccApplicationsEnabled);
320 return ScopedAStatus::ok();
321 }
322
changeIccPin2ForApp(int32_t serial,const std::string & oldPin2,const std::string & newPin2,const std::string &)323 ScopedAStatus RadioSim::changeIccPin2ForApp(int32_t serial,
324 const std::string& oldPin2,
325 const std::string& newPin2,
326 const std::string& /*aid*/) {
327 mAtChannel->queueRequester([this, serial, oldPin2, newPin2]
328 (const AtChannel::RequestPipe requestPipe) -> bool {
329 const auto [status, remainingRetries] =
330 enterOrChangeSimPinPuk(true, oldPin2, newPin2, "SIM PIN2"sv,
331 requestPipe, mAtConversation);
332
333 NOT_NULL(mRadioSimResponse)->supplyIccPin2ForAppResponse(
334 makeRadioResponseInfo(serial, status), remainingRetries);
335 return status != RadioError::INTERNAL_ERR;
336 });
337
338 return ScopedAStatus::ok();
339 }
340
changeIccPinForApp(const int32_t serial,const std::string & oldPin,const std::string & newPin,const std::string &)341 ScopedAStatus RadioSim::changeIccPinForApp(const int32_t serial,
342 const std::string& oldPin,
343 const std::string& newPin,
344 const std::string& /*aid*/) {
345 mAtChannel->queueRequester([this, serial, oldPin, newPin]
346 (const AtChannel::RequestPipe requestPipe) -> bool {
347 const auto [status, remainingRetries] =
348 enterOrChangeSimPinPuk(true, oldPin, newPin, "SIM PIN"sv,
349 requestPipe, mAtConversation);
350
351 NOT_NULL(mRadioSimResponse)->changeIccPinForAppResponse(
352 makeRadioResponseInfo(serial, status), remainingRetries);
353 return status != RadioError::INTERNAL_ERR;
354 });
355
356 return ScopedAStatus::ok();
357 }
358
enableUiccApplications(const int32_t serial,const bool enable)359 ScopedAStatus RadioSim::enableUiccApplications(const int32_t serial, const bool enable) {
360 bool changed;
361 {
362 std::lock_guard<std::mutex> lock(mMtx);
363 changed = mUiccApplicationsEnabled != enable;
364 mUiccApplicationsEnabled = enable;
365 }
366
367 NOT_NULL(mRadioSimResponse)->enableUiccApplicationsResponse(
368 makeRadioResponseInfo(serial));
369
370 if (changed && mRadioSimIndication) {
371 mRadioSimIndication->uiccApplicationsEnablementChanged(
372 RadioIndicationType::UNSOLICITED, enable);
373 }
374 return ScopedAStatus::ok();
375 }
376
getAllowedCarriers(const int32_t serial)377 ScopedAStatus RadioSim::getAllowedCarriers(const int32_t serial) {
378 static const char* const kFunc = __func__;
379 mAtChannel->queueRequester([this, serial](const AtChannel::RequestPipe requestPipe) -> bool {
380 using sim::CarrierInfo;
381 using sim::CarrierRestrictions;
382 using sim::SimLockMultiSimPolicy;
383 using CmeError = AtResponse::CmeError;
384 using COPS = AtResponse::COPS;
385
386 RadioError status = RadioError::NONE;
387 CarrierRestrictions carrierRestrictions = {
388 .allowedCarriersPrioritized = true,
389 };
390
391 const AtResponsePtr response =
392 mAtConversation(requestPipe, atCmds::getOperator,
393 [](const AtResponse& response) -> bool {
394 return response.holds<COPS>() || response.holds<CmeError>();
395 });
396 if (!response || response->isParseError()) {
397 status = FAILURE(RadioError::INTERNAL_ERR);
398 } else if (const COPS* cops = response->get_if<COPS>()) {
399 if ((cops->operators.size() == 1) && (cops->operators[0].isCurrent())) {
400 const COPS::OperatorInfo& current = cops->operators[0];
401 CarrierInfo ci = {
402 .mcc = current.mcc(),
403 .mnc = current.mnc(),
404 };
405
406 carrierRestrictions.allowedCarrierInfoList.push_back(std::move(ci));
407 } else {
408 response->unexpected(FAILURE_DEBUG_PREFIX, __func__);
409 }
410 } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
411 status = cmeError->getErrorAndLog(FAILURE_DEBUG_PREFIX, kFunc, __LINE__);
412 } else {
413 response->unexpected(FAILURE_DEBUG_PREFIX, __func__);
414 }
415
416 NOT_NULL(mRadioSimResponse)->getAllowedCarriersResponse(
417 makeRadioResponseInfo(serial, status),
418 std::move(carrierRestrictions),
419 SimLockMultiSimPolicy::NO_MULTISIM_POLICY);
420 return status != RadioError::INTERNAL_ERR;
421 });
422
423 return ScopedAStatus::ok();
424 }
425
getCdmaSubscription(const int32_t serial)426 ScopedAStatus RadioSim::getCdmaSubscription(const int32_t serial) {
427 NOT_NULL(mRadioSimResponse)->getCdmaSubscriptionResponse(
428 makeRadioResponseInfo(serial),
429 "8587777777", // mdn
430 "1", // sid
431 "1", // nid
432 "8587777777", // min
433 "1"); // prl
434 return ScopedAStatus::ok();
435 }
436
getCdmaSubscriptionSource(const int32_t serial)437 ScopedAStatus RadioSim::getCdmaSubscriptionSource(const int32_t serial) {
438 static const char* const kFunc = __func__;
439 mAtChannel->queueRequester([this, serial](const AtChannel::RequestPipe requestPipe) -> bool {
440 using CCSS = AtResponse::CCSS;
441
442 AtResponsePtr response =
443 mAtConversation(requestPipe, atCmds::getCdmaSubscriptionSource,
444 [](const AtResponse& response) -> bool {
445 return response.holds<CCSS>();
446 });
447 if (!response || response->isParseError()) {
448 NOT_NULL(mRadioSimResponse)->getCdmaSubscriptionSourceResponse(
449 makeRadioResponseInfo(serial, RadioError::INTERNAL_ERR), {});
450 return false;
451 } else if (const CCSS* csss = response->get_if<CCSS>()) {
452 NOT_NULL(mRadioSimResponse)->getCdmaSubscriptionSourceResponse(
453 makeRadioResponseInfo(serial), csss->source);
454 } else {
455 response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
456 }
457
458 return true;
459 });
460
461 return ScopedAStatus::ok();
462 }
463
getFacilityLockForApp(const int32_t serial,const std::string & facility,const std::string & password,const int32_t serviceClass,const std::string &)464 ScopedAStatus RadioSim::getFacilityLockForApp(const int32_t serial, const std::string& facility,
465 const std::string& password, const int32_t serviceClass,
466 const std::string& /*appId*/) {
467 std::string request = std::format("AT+CLCK=\"{0:s}\",{1:d},\"{2:s}\",{3:d}",
468 facility, atCmds::kClckQuery, password, serviceClass);
469
470 static const char* const kFunc = __func__;
471 mAtChannel->queueRequester([this, serial, request = std::move(request)]
472 (const AtChannel::RequestPipe requestPipe) -> bool {
473 using CmeError = AtResponse::CmeError;
474 using CLCK = AtResponse::CLCK;
475
476 RadioError status = RadioError::NONE;
477 int lockBitmask = 0;
478
479 AtResponsePtr response =
480 mAtConversation(requestPipe, request,
481 [](const AtResponse& response) -> bool {
482 return response.holds<CLCK>() || response.holds<CmeError>();
483 });
484 if (!response || response->isParseError()) {
485 status = FAILURE(RadioError::INTERNAL_ERR);
486 } else if (const CLCK* clck = response->get_if<CLCK>()) {
487 lockBitmask = clck->locked ? 7 : 0;
488 } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
489 status = cmeError->getErrorAndLog(FAILURE_DEBUG_PREFIX, kFunc, __LINE__);
490 } else {
491 response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
492 }
493
494 NOT_NULL(mRadioSimResponse)->getFacilityLockForAppResponse(
495 makeRadioResponseInfo(serial, status), lockBitmask);
496 return status != RadioError::INTERNAL_ERR;
497 });
498
499 return ScopedAStatus::ok();
500 }
501
getIccCardStatus(const int32_t serial)502 ScopedAStatus RadioSim::getIccCardStatus(const int32_t serial) {
503 using sim::AppStatus;
504 using sim::PersoSubstate;
505 using sim::PinState;
506
507 struct AppStatus3 {
508 AppStatus usim;
509 AppStatus ruim;
510 AppStatus isim;
511 };
512
513 static const std::string kAidPtr = ""; //"A0000000871002FF86FF0389FFFFFFFF";
514 static const std::string kAppLabelPtr = "";
515
516 static const std::string kATR = ""; //"3BF000818000";
517 // This data is mandatory and applicable only when cardState is
518 // STATE_PRESENT and SIM card supports eUICC.
519 static const std::string kEID = "";
520
521 static const AppStatus3 kIccStatusReady = {
522 .usim = {
523 AppStatus::APP_TYPE_USIM, AppStatus::APP_STATE_READY, PersoSubstate::READY,
524 kAidPtr, kAppLabelPtr, false, PinState::UNKNOWN, PinState::UNKNOWN
525 },
526 .ruim = {
527 AppStatus::APP_TYPE_RUIM, AppStatus::APP_STATE_READY, PersoSubstate::READY,
528 kAidPtr, kAppLabelPtr, false, PinState::UNKNOWN, PinState::UNKNOWN
529 },
530 .isim = {
531 AppStatus::APP_TYPE_ISIM, AppStatus::APP_STATE_READY, PersoSubstate::READY,
532 kAidPtr, kAppLabelPtr, false, PinState::UNKNOWN, PinState::UNKNOWN
533 }
534 };
535
536 static const AppStatus3 kIccStatusPIN = {
537 .usim = {
538 AppStatus::APP_TYPE_USIM, AppStatus::APP_STATE_PIN, PersoSubstate::UNKNOWN,
539 kAidPtr, kAppLabelPtr, false, PinState::ENABLED_NOT_VERIFIED, PinState::ENABLED_NOT_VERIFIED
540 },
541 .ruim = {
542 AppStatus::APP_TYPE_RUIM, AppStatus::APP_STATE_PIN, PersoSubstate::UNKNOWN,
543 kAidPtr, kAppLabelPtr, false, PinState::ENABLED_NOT_VERIFIED, PinState::ENABLED_NOT_VERIFIED
544 },
545 .isim = {
546 AppStatus::APP_TYPE_ISIM, AppStatus::APP_STATE_PIN, PersoSubstate::UNKNOWN,
547 kAidPtr, kAppLabelPtr, false, PinState::ENABLED_NOT_VERIFIED, PinState::ENABLED_NOT_VERIFIED
548 }
549 };
550
551 static const AppStatus3 kIccStatusPUK = {
552 .usim = {
553 AppStatus::APP_TYPE_USIM, AppStatus::APP_STATE_PUK, PersoSubstate::UNKNOWN,
554 kAidPtr, kAppLabelPtr, false, PinState::ENABLED_NOT_VERIFIED, PinState::ENABLED_NOT_VERIFIED
555 },
556 .ruim = {
557 AppStatus::APP_TYPE_RUIM, AppStatus::APP_STATE_PUK, PersoSubstate::UNKNOWN,
558 kAidPtr, kAppLabelPtr, false, PinState::ENABLED_NOT_VERIFIED, PinState::ENABLED_NOT_VERIFIED
559 },
560 .isim = {
561 AppStatus::APP_TYPE_ISIM, AppStatus::APP_STATE_PUK, PersoSubstate::UNKNOWN,
562 kAidPtr, kAppLabelPtr, false, PinState::ENABLED_NOT_VERIFIED, PinState::ENABLED_NOT_VERIFIED
563 }
564 };
565
566 static const AppStatus3 kIccStatusBUSY = {
567 .usim = {
568 AppStatus::APP_TYPE_USIM, AppStatus::APP_STATE_DETECTED, PersoSubstate::UNKNOWN,
569 kAidPtr, kAppLabelPtr, false, PinState::UNKNOWN, PinState::UNKNOWN
570 },
571 .ruim = {
572 AppStatus::APP_TYPE_RUIM, AppStatus::APP_STATE_DETECTED, PersoSubstate::UNKNOWN,
573 kAidPtr, kAppLabelPtr, false, PinState::UNKNOWN, PinState::UNKNOWN
574 },
575 .isim = {
576 AppStatus::APP_TYPE_ISIM, AppStatus::APP_STATE_DETECTED, PersoSubstate::UNKNOWN,
577 kAidPtr, kAppLabelPtr, false, PinState::UNKNOWN, PinState::UNKNOWN
578 }
579 };
580
581 static const char* const kFunc = __func__;
582 mAtChannel->queueRequester([this, serial](const AtChannel::RequestPipe requestPipe) -> bool {
583 using sim::CardStatus;
584 using CmeError = AtResponse::CmeError;
585 using CPIN = AtResponse::CPIN;
586
587 RadioError status = RadioError::NONE;
588 CardStatus cardStatus = {
589 .slotMap = {
590 .physicalSlotId = -1, // see ril_service.cpp in CF
591 .portId = 0,
592 }
593 };
594
595 const AppStatus3* appStatus = nullptr;
596
597 AtResponsePtr response =
598 mAtConversation(requestPipe, atCmds::getSimCardStatus,
599 [](const AtResponse& response) -> bool {
600 return response.holds<CPIN>() || response.holds<CmeError>();
601 });
602 if (!response || response->isParseError()) {
603 status = FAILURE(RadioError::INTERNAL_ERR);
604 goto failed;
605 } else if (const CPIN* cpin = response->get_if<CPIN>()) {
606 switch (cpin->state) {
607 case CPIN::State::READY:
608 cardStatus.cardState = sim::CardStatus::STATE_PRESENT;
609 cardStatus.universalPinState = sim::PinState::UNKNOWN;
610 appStatus = &kIccStatusReady;
611 break;
612
613 case CPIN::State::PIN:
614 cardStatus.cardState = sim::CardStatus::STATE_RESTRICTED;
615 cardStatus.universalPinState = sim::PinState::ENABLED_NOT_VERIFIED;
616 appStatus = &kIccStatusPIN;
617 break;
618
619 case CPIN::State::PUK:
620 cardStatus.cardState = sim::CardStatus::STATE_RESTRICTED;
621 cardStatus.universalPinState = sim::PinState::ENABLED_NOT_VERIFIED;
622 appStatus = &kIccStatusPUK;
623 break;
624
625 default:
626 status = FAILURE(RadioError::INTERNAL_ERR);
627 goto failed;
628 }
629 } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
630 switch (cmeError->error) {
631 case RadioError::SIM_ABSENT:
632 cardStatus.cardState = sim::CardStatus::STATE_ABSENT;
633 cardStatus.universalPinState = sim::PinState::UNKNOWN;
634 break;
635
636 case RadioError::SIM_BUSY:
637 case RadioError::SIM_ERR:
638 cardStatus.cardState = sim::CardStatus::STATE_ERROR;
639 cardStatus.universalPinState = sim::PinState::UNKNOWN;
640 appStatus = &kIccStatusBUSY;
641 break;
642
643 default:
644 status = cmeError->getErrorAndLog(
645 FAILURE_DEBUG_PREFIX, kFunc, __LINE__);
646 goto failed;
647 }
648 } else {
649 response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
650 }
651
652 if (cardStatus.cardState != sim::CardStatus::STATE_ABSENT) {
653 response =
654 mAtConversation(requestPipe, atCmds::getICCID,
655 [](const AtResponse& response) -> bool {
656 return response.holds<std::string>();
657 });
658 if (!response || response->isParseError()) {
659 status = FAILURE(RadioError::INTERNAL_ERR);
660 goto failed;
661 } else if (const std::string* iccid = response->get_if<std::string>()) {
662 cardStatus.iccid = *iccid;
663 } else {
664 response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
665 }
666
667 cardStatus.applications.push_back(appStatus->usim);
668 cardStatus.applications.push_back(appStatus->ruim);
669 cardStatus.applications.push_back(appStatus->isim);
670 cardStatus.gsmUmtsSubscriptionAppIndex = 0; // usim
671 cardStatus.cdmaSubscriptionAppIndex = 1; // ruim
672 cardStatus.imsSubscriptionAppIndex = 2; // isim
673
674 cardStatus.atr = kATR;
675 cardStatus.eid = kEID;
676 }
677
678 if (status == RadioError::NONE) {
679 NOT_NULL(mRadioSimResponse)->getIccCardStatusResponse(
680 makeRadioResponseInfo(serial), std::move(cardStatus));
681 return true;
682 } else {
683 failed: NOT_NULL(mRadioSimResponse)->getIccCardStatusResponse(
684 makeRadioResponseInfo(serial, status), {});
685 return status != RadioError::INTERNAL_ERR;
686 }
687 });
688
689 return ScopedAStatus::ok();
690 }
691
getImsiForApp(const int32_t serial,const std::string &)692 ScopedAStatus RadioSim::getImsiForApp(const int32_t serial, const std::string& /*aid*/) {
693 static const char* const kFunc = __func__;
694 mAtChannel->queueRequester([this, serial](const AtChannel::RequestPipe requestPipe) -> bool {
695 using CmeError = AtResponse::CmeError;
696
697 RadioError status = RadioError::NONE;
698 std::string imsi;
699
700 AtResponsePtr response =
701 mAtConversation(requestPipe, atCmds::getIMSI,
702 [](const AtResponse& response) -> bool {
703 return response.holds<std::string>() || response.holds<CmeError>();
704 });
705 if (!response || response->isParseError()) {
706 status = FAILURE(RadioError::INTERNAL_ERR);
707 } else if (const std::string* pImsi = response->get_if<std::string>()) {
708 imsi = *pImsi;
709 } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
710 status = cmeError->getErrorAndLog(FAILURE_DEBUG_PREFIX, kFunc, __LINE__);
711 } else {
712 response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
713 }
714
715 if (status == RadioError::NONE) {
716 NOT_NULL(mRadioSimResponse)->getImsiForAppResponse(
717 makeRadioResponseInfo(serial), std::move(imsi));
718 return true;
719 } else {
720 NOT_NULL(mRadioSimResponse)->getImsiForAppResponse(
721 makeRadioResponseInfo(serial, FAILURE(status)), {});
722 return status != RadioError::INTERNAL_ERR;
723 }
724 });
725
726 return ScopedAStatus::ok();
727 }
728
getSimPhonebookCapacity(const int32_t serial)729 ScopedAStatus RadioSim::getSimPhonebookCapacity(const int32_t serial) {
730 NOT_NULL(mRadioSimResponse)->getSimPhonebookCapacityResponse(
731 makeRadioResponseInfoUnsupported( // matches reference-ril.c
732 serial, FAILURE_DEBUG_PREFIX, __func__), {});
733 return ScopedAStatus::ok();
734 }
735
getSimPhonebookRecords(const int32_t serial)736 ScopedAStatus RadioSim::getSimPhonebookRecords(const int32_t serial) {
737 NOT_NULL(mRadioSimResponse)->getSimPhonebookRecordsResponse(
738 makeRadioResponseInfoUnsupported( // matches reference-ril.c
739 serial, FAILURE_DEBUG_PREFIX, __func__));
740 return ScopedAStatus::ok();
741 }
742
iccCloseLogicalChannelWithSessionInfo(const int32_t serial,const sim::SessionInfo & recordInfo)743 ScopedAStatus RadioSim::iccCloseLogicalChannelWithSessionInfo(const int32_t serial,
744 const sim::SessionInfo& recordInfo) {
745 const int32_t sessionId = recordInfo.sessionId;
746
747 static const char* const kFunc = __func__;
748 mAtChannel->queueRequester([this, serial, sessionId](const AtChannel::RequestPipe requestPipe) -> bool {
749 using CCHC = AtResponse::CCHC;
750 using CmeError = AtResponse::CmeError;
751
752 RadioError status = RadioError::NONE;
753
754 const std::string request = std::format("AT+CCHC={0:d}", sessionId);
755 AtResponsePtr response =
756 mAtConversation(requestPipe, request,
757 [](const AtResponse& response) -> bool {
758 return response.holds<CCHC>() || response.holds<CmeError>();
759 });
760 if (!response || response->isParseError()) {
761 status = FAILURE(RadioError::INTERNAL_ERR);
762 } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
763 status = cmeError->getErrorAndLog(FAILURE_DEBUG_PREFIX, kFunc, __LINE__);
764 if (status == RadioError::NO_SUCH_ELEMENT) {
765 status = RadioError::INVALID_ARGUMENTS;
766 }
767 } else if (!response->get_if<CCHC>()) {
768 response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
769 }
770
771 NOT_NULL(mRadioSimResponse)->iccCloseLogicalChannelWithSessionInfoResponse(
772 makeRadioResponseInfo(serial, status));
773 return status != RadioError::INTERNAL_ERR;
774 });
775
776 return ScopedAStatus::ok();
777 }
778
iccIoForApp(const int32_t serial,const sim::IccIo & iccIo)779 ScopedAStatus RadioSim::iccIoForApp(const int32_t serial, const sim::IccIo& iccIo) {
780 static const char* const kFunc = __func__;
781 mAtChannel->queueRequester([this, serial, iccIo]
782 (const AtChannel::RequestPipe requestPipe) -> bool {
783 using CRSM = AtResponse::CRSM;
784 using CmeError = AtResponse::CmeError;
785 using sim::IccIoResult;
786
787 RadioError status = RadioError::NONE;
788 IccIoResult iccIoResult;
789
790 std::string request;
791 if (iccIo.data.empty()) {
792 request = std::format("AT+CRSM={0:d},{1:d},{2:d},{3:d},{4:d}",
793 iccIo.command, iccIo.fileId, iccIo.p1, iccIo.p2, iccIo.p3);
794 } else {
795 request = std::format("AT+CRSM={0:d},{1:d},{2:d},{3:d},{4:d},{5:s},{6:s}",
796 iccIo.command, iccIo.fileId, iccIo.p1, iccIo.p2, iccIo.p3,
797 iccIo.data, iccIo.aid);
798 }
799
800 AtResponsePtr response =
801 mAtConversation(requestPipe, request,
802 [](const AtResponse& response) -> bool {
803 return response.holds<CRSM>() || response.holds<CmeError>();
804 });
805 if (!response || response->isParseError()) {
806 status = FAILURE(RadioError::INTERNAL_ERR);
807 } else if (const CRSM* crsm = response->get_if<CRSM>()) {
808 iccIoResult.sw1 = crsm->sw1;
809 iccIoResult.sw2 = crsm->sw2;
810
811 if (iccIo.command == 192) { // get
812 std::vector<uint8_t> bytes;
813 if (hex2bin(crsm->response, &bytes) && !bytes.empty() && (bytes.front() == 0x62)) {
814 if (!convertUsimToSim(bytes, &iccIoResult.simResponse)) {
815 status = FAILURE(RadioError::GENERIC_FAILURE);
816 }
817 } else {
818 iccIoResult.simResponse = crsm->response;
819 }
820 } else {
821 iccIoResult.simResponse = crsm->response;
822 }
823 } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
824 status = cmeError->getErrorAndLog(FAILURE_DEBUG_PREFIX, kFunc, __LINE__);
825 } else {
826 response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
827 }
828
829 if (status == RadioError::NONE) {
830 NOT_NULL(mRadioSimResponse)->iccIoForAppResponse(
831 makeRadioResponseInfo(serial), std::move(iccIoResult));
832 return true;
833 } else {
834 NOT_NULL(mRadioSimResponse)->iccIoForAppResponse(
835 makeRadioResponseInfo(serial, status), {});
836 return status != RadioError::INTERNAL_ERR;
837 }
838 });
839
840 return ScopedAStatus::ok();
841 }
842
iccOpenLogicalChannel(const int32_t serial,const std::string & aid,const int32_t p2)843 ScopedAStatus RadioSim::iccOpenLogicalChannel(const int32_t serial,
844 const std::string& aid,
845 const int32_t p2) {
846 static const char* const kFunc = __func__;
847 mAtChannel->queueRequester([this, serial, aid, p2](const AtChannel::RequestPipe requestPipe) -> bool {
848 using CSIM = AtResponse::CSIM;
849 using CmeError = AtResponse::CmeError;
850
851 RadioError status = RadioError::NONE;
852 int channelId = 0;
853 std::vector<uint8_t> selectResponse;
854
855 if (aid.empty()) {
856 AtResponsePtr response =
857 mAtConversation(requestPipe, "AT+CSIM=10,\"0070000001\""sv,
858 [](const AtResponse& response) -> bool {
859 return response.holds<CSIM>() || response.holds<CmeError>();
860 });
861 if (!response || response->isParseError()) {
862 status = FAILURE(RadioError::INTERNAL_ERR);
863 } else if (const CSIM* csim = response->get_if<CSIM>()) {
864 if (1 == ::sscanf(csim->response.c_str(), "%02x", &channelId)) {
865 if (p2 >= 0) {
866 auto maybeSelectResponse =
867 getSelectResponse(requestPipe, mAtConversation,
868 channelId, p2);
869 if (maybeSelectResponse) {
870 selectResponse = std::move(maybeSelectResponse.value());
871 } else {
872 requestPipe(std::format("AT+CCHC={0:d}", channelId));
873 status = FAILURE(RadioError::GENERIC_FAILURE);
874 }
875 } else {
876 if (!hex2bin(std::string_view(csim->response).substr(2),
877 &selectResponse)) {
878 status = FAILURE(RadioError::GENERIC_FAILURE);
879 }
880 }
881 } else {
882 status = FAILURE(RadioError::GENERIC_FAILURE);
883 }
884 } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
885 status = cmeError->getErrorAndLog(FAILURE_DEBUG_PREFIX, kFunc, __LINE__);
886 } else {
887 response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
888 }
889 } else {
890 const std::string request = std::format("AT+CCHO={0:s}", aid);
891 AtResponsePtr response =
892 mAtConversation(requestPipe, request,
893 [](const AtResponse& response) -> bool {
894 return response.holds<std::string>() || response.holds<CmeError>();
895 });
896 if (!response || response->isParseError()) {
897 status = FAILURE(RadioError::INTERNAL_ERR);
898 } else if (const std::string* idStr = response->get_if<std::string>()) {
899 const char* end = idStr->data() + idStr->size();
900
901 if (std::from_chars(idStr->data(), end, channelId, 10).ptr != end) {
902 status = FAILURE(RadioError::INTERNAL_ERR);
903 }
904 } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
905 status = cmeError->getErrorAndLog(FAILURE_DEBUG_PREFIX, kFunc, __LINE__);
906 } else {
907 response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
908 }
909 }
910
911 NOT_NULL(mRadioSimResponse)->iccOpenLogicalChannelResponse(
912 makeRadioResponseInfo(serial, status), channelId, std::move(selectResponse));
913 return status != RadioError::INTERNAL_ERR;
914 });
915
916 return ScopedAStatus::ok();
917 }
918
iccTransmitApduBasicChannel(const int32_t serial,const sim::SimApdu & message)919 ScopedAStatus RadioSim::iccTransmitApduBasicChannel(const int32_t serial,
920 const sim::SimApdu& message) {
921 static const char* const kFunc = __func__;
922 mAtChannel->queueRequester([this, serial, message]
923 (const AtChannel::RequestPipe requestPipe) -> bool {
924 using CSIM = AtResponse::CSIM;
925 using CmeError = AtResponse::CmeError;
926 using sim::IccIoResult;
927
928 RadioError status = RadioError::NONE;
929 IccIoResult iccIoResult;
930
931 std::string request;
932 if (message.data.empty()) {
933 if (message.p3 < 0) {
934 request = std::format(
935 "AT+CSIM={0:d},\"{1:02x}{2:02x}{3:02x}{4:02x}\"", 8,
936 message.cla, message.instruction, message.p1, message.p2);
937 } else {
938 request = std::format(
939 "AT+CSIM={0:d},\"{1:02x}{2:02x}{3:02x}{4:02x}{5:02x}\"", 10,
940 message.cla, message.instruction, message.p1, message.p2, message.p3);
941 }
942 } else {
943 const size_t dataSize = 10 + message.data.size();
944 request = std::format(
945 "AT+CSIM={0:d},\"{1:02x}{2:02x}{3:02x}{4:02x}{5:02x}{6:s}\"",
946 dataSize, message.cla, message.instruction, message.p1,
947 message.p2, message.p3, message.data);
948 }
949
950 AtResponsePtr response =
951 mAtConversation(requestPipe, request,
952 [](const AtResponse& response) -> bool {
953 return response.holds<CSIM>() || response.holds<CmeError>();
954 });
955 if (!response || response->isParseError()) {
956 status = FAILURE(RadioError::INTERNAL_ERR);
957 } else if (const CSIM* csim = response->get_if<CSIM>()) {
958 const std::string& simResponse = csim->response;
959 if (simResponse.size() >= 4) {
960 if (2 == ::sscanf(&simResponse[simResponse.size() - 4], "%02X%02X",
961 &iccIoResult.sw1, &iccIoResult.sw2)) {
962 iccIoResult.simResponse = simResponse.substr(0, simResponse.size() - 4);
963 } else {
964 status = FAILURE(RadioError::GENERIC_FAILURE);
965 }
966 } else {
967 status = FAILURE(RadioError::GENERIC_FAILURE);
968 }
969 } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
970 status = cmeError->getErrorAndLog(FAILURE_DEBUG_PREFIX, kFunc, __LINE__);
971 } else {
972 response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
973 }
974
975 if (status == RadioError::NONE) {
976 NOT_NULL(mRadioSimResponse)->iccTransmitApduBasicChannelResponse(
977 makeRadioResponseInfo(serial), std::move(iccIoResult));
978 return true;
979 } else {
980 NOT_NULL(mRadioSimResponse)->iccTransmitApduBasicChannelResponse(
981 makeRadioResponseInfo(serial, status), {});
982 return status != RadioError::INTERNAL_ERR;
983 }
984 });
985
986 return ScopedAStatus::ok();
987 }
988
iccTransmitApduLogicalChannel(const int32_t serial,const sim::SimApdu & message)989 ScopedAStatus RadioSim::iccTransmitApduLogicalChannel(
990 const int32_t serial, const sim::SimApdu& message) {
991 static const char* const kFunc = __func__;
992 mAtChannel->queueRequester([this, serial, message]
993 (const AtChannel::RequestPipe requestPipe) -> bool {
994 using CGLA = AtResponse::CGLA;
995 using CmeError = AtResponse::CmeError;
996 using sim::IccIoResult;
997
998 RadioError status = RadioError::NONE;
999 IccIoResult iccIoResult;
1000
1001 const size_t dataSize = 10 + message.data.size();
1002 const std::string request = std::format(
1003 "AT+CGLA={0:d},{1:d},{2:02x}{3:02x}{4:02x}{5:02x}{6:02x}{7:s}",
1004 message.sessionId, dataSize,
1005 message.cla, message.instruction, message.p1,
1006 message.p2, message.p3, message.data);
1007 AtResponsePtr response =
1008 mAtConversation(requestPipe, request,
1009 [](const AtResponse& response) -> bool {
1010 return response.holds<CGLA>() || response.holds<CmeError>();
1011 });
1012 if (!response || response->isParseError()) {
1013 status = FAILURE(RadioError::INTERNAL_ERR);
1014 } else if (const CGLA* cgla = response->get_if<CGLA>()) {
1015 if (cgla->response.size() >= 4) {
1016 const size_t size4 = cgla->response.size() - 4;
1017 if (2 == ::sscanf(&cgla->response[size4], "%02x%02x",
1018 &iccIoResult.sw1, &iccIoResult.sw2)) {
1019 iccIoResult.simResponse = cgla->response.substr(0, size4);
1020 } else {
1021 status = FAILURE(RadioError::GENERIC_FAILURE);
1022 }
1023 } else {
1024 status = FAILURE(RadioError::GENERIC_FAILURE);
1025 }
1026 } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
1027 status = cmeError->getErrorAndLog(FAILURE_DEBUG_PREFIX, kFunc, __LINE__);
1028 } else {
1029 response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
1030 }
1031
1032 if (status == RadioError::NONE) {
1033 NOT_NULL(mRadioSimResponse)->iccTransmitApduLogicalChannelResponse(
1034 makeRadioResponseInfo(serial), std::move(iccIoResult));
1035 return true;
1036 } else {
1037 NOT_NULL(mRadioSimResponse)->iccTransmitApduLogicalChannelResponse(
1038 makeRadioResponseInfo(serial, status), {});
1039 return status != RadioError::INTERNAL_ERR;
1040 }
1041 });
1042
1043 return ScopedAStatus::ok();
1044 }
1045
reportStkServiceIsRunning(const int32_t serial)1046 ScopedAStatus RadioSim::reportStkServiceIsRunning(const int32_t serial) {
1047 decltype(mStkUnsolResponse) stkUnsolResponse;
1048 {
1049 std::lock_guard<std::mutex> lock(mMtx);
1050 mStkServiceRunning = true;
1051 stkUnsolResponse = std::move(mStkUnsolResponse);
1052 }
1053
1054 if (stkUnsolResponse) {
1055 NOT_NULL(mRadioSimIndication)->stkProactiveCommand(
1056 RadioIndicationType::UNSOLICITED, std::move(stkUnsolResponse.value().cmd));
1057 }
1058
1059 static const char* const kFunc = __func__;
1060 mAtChannel->queueRequester([this, serial]
1061 (const AtChannel::RequestPipe requestPipe) -> bool {
1062 using CUSATD = AtResponse::CUSATD;
1063
1064 RadioError status = RadioError::NONE;
1065
1066 AtResponsePtr response =
1067 mAtConversation(requestPipe, atCmds::reportStkServiceRunning,
1068 [](const AtResponse& response) -> bool {
1069 return response.holds<CUSATD>();
1070 });
1071 if (!response || response->isParseError()) {
1072 status = FAILURE(RadioError::INTERNAL_ERR);
1073 } else if (!response->get_if<CUSATD>()) {
1074 response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
1075 }
1076
1077 NOT_NULL(mRadioSimResponse)->reportStkServiceIsRunningResponse(
1078 makeRadioResponseInfo(serial, status));
1079 return status != RadioError::INTERNAL_ERR;
1080 });
1081
1082 return ScopedAStatus::ok();
1083 }
1084
requestIccSimAuthentication(const int32_t serial,const int32_t authContextInt,const std::string & authData64,const std::string &)1085 ScopedAStatus RadioSim::requestIccSimAuthentication(const int32_t serial,
1086 const int32_t authContextInt,
1087 const std::string& authData64,
1088 const std::string& /*aid*/) {
1089 const AuthContext authContext = static_cast<AuthContext>(authContextInt);
1090
1091 auto [status, randBin, authBin] = parseAuthData(authContext, authData64);
1092 if (status != RadioError::NONE) {
1093 NOT_NULL(mRadioSimResponse)->requestIccSimAuthenticationResponse(
1094 makeRadioResponseInfo(serial, status), {});
1095 return ScopedAStatus::ok();
1096 }
1097
1098 std::string randHex = bin2hex(randBin.data(), randBin.size());
1099 std::string authHex = bin2hex(authBin.data(), authBin.size());
1100
1101 static const char* const kFunc = __func__;
1102 mAtChannel->queueRequester([this, serial, authContext,
1103 randHex = std::move(randHex),
1104 authHex = std::move(authHex)]
1105 (const AtChannel::RequestPipe requestPipe) -> bool {
1106 using CmeError = AtResponse::CmeError;
1107 using MBAU = AtResponse::MBAU;
1108 using sim::IccIoResult;
1109
1110 RadioError status = RadioError::NONE;
1111 IccIoResult iccIoResult;
1112
1113 std::string request;
1114 switch (authContext) {
1115 case AuthContext::SIM:
1116 request = std::format("AT^MBAU=\"{0:s}\"", randHex);
1117 break;
1118
1119 case AuthContext::AKA:
1120 request = std::format("AT^MBAU=\"{0:s},{1:s}\"", randHex, authHex); // the quotes are interesting here
1121 break;
1122
1123 default:
1124 return FAILURE(false);
1125 }
1126
1127 AtResponsePtr response =
1128 mAtConversation(requestPipe, request,
1129 [](const AtResponse& response) -> bool {
1130 return response.holds<MBAU>() ||
1131 response.holds<CmeError>();
1132 });
1133 if (!response || response->isParseError()) {
1134 status = FAILURE(RadioError::INTERNAL_ERR);
1135 } else if (const MBAU* mbau = response->get_if<MBAU>()) {
1136 const auto putByte = [](uint8_t* dst, uint8_t b) -> uint8_t* {
1137 *dst = b;
1138 return dst + 1;
1139 };
1140
1141 const auto putRange = [](uint8_t* dst, const uint8_t* src, size_t size) -> uint8_t* {
1142 memcpy(dst, src, size);
1143 return dst + size;
1144 };
1145
1146 const auto putSizedRange = [putByte, putRange](uint8_t* dst, const uint8_t* src, size_t size) -> uint8_t* {
1147 return putRange(putByte(dst, size), src, size);
1148 };
1149
1150 std::vector<uint8_t> responseBin;
1151 uint8_t* p;
1152
1153 switch (authContext) {
1154 case AuthContext::SIM: // sresLen + sres + kcLen + kc
1155 responseBin.resize(2 + mbau->sres.size() + mbau->kc.size());
1156 p = responseBin.data();
1157 p = putSizedRange(p, mbau->sres.data(), mbau->sres.size());
1158 p = putSizedRange(p, mbau->kc.data(), mbau->kc.size());
1159 break;
1160
1161 case AuthContext::AKA: // 0xDB + ckLen + ck + ikLen + ik + resAutsLen + resAuts
1162 responseBin.resize(4 + mbau->ck.size() + mbau->ik.size() + mbau->resAuts.size());
1163 p = responseBin.data();
1164 p = putByte(p, 0xDB);
1165 p = putSizedRange(p, mbau->ck.data(), mbau->ck.size());
1166 p = putSizedRange(p, mbau->ik.data(), mbau->ik.size());
1167 p = putSizedRange(p, mbau->resAuts.data(), mbau->resAuts.size());
1168 break;
1169 }
1170
1171 iccIoResult.sw1 = 0x90;
1172 iccIoResult.sw2 = 0;
1173 iccIoResult.simResponse = base64encode(responseBin.data(), responseBin.size());
1174 } else if (response->isOK()) {
1175 status = FAILURE(RadioError::GENERIC_FAILURE);
1176 } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
1177 status = cmeError->getErrorAndLog(FAILURE_DEBUG_PREFIX, kFunc, __LINE__);
1178 } else {
1179 response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
1180 }
1181
1182 if (status == RadioError::NONE) {
1183 NOT_NULL(mRadioSimResponse)->requestIccSimAuthenticationResponse(
1184 makeRadioResponseInfo(serial), std::move(iccIoResult));
1185 return true;
1186 } else {
1187 NOT_NULL(mRadioSimResponse)->requestIccSimAuthenticationResponse(
1188 makeRadioResponseInfo(serial, status), {});
1189 return status != RadioError::INTERNAL_ERR;
1190 }
1191 });
1192
1193 return ScopedAStatus::ok();
1194 }
1195
sendEnvelope(const int32_t serial,const std::string & contents)1196 ScopedAStatus RadioSim::sendEnvelope(const int32_t serial,
1197 const std::string& contents) {
1198 static const char* const kFunc = __func__;
1199 mAtChannel->queueRequester([this, serial, contents]
1200 (const AtChannel::RequestPipe requestPipe) -> bool {
1201 using CUSATE = AtResponse::CUSATE;
1202 RadioError status = RadioError::NONE;
1203 std::string commandResponse;
1204
1205 const std::string request = std::format("AT+CUSATE=\"{0:s}\"", contents);
1206 AtResponsePtr response =
1207 mAtConversation(requestPipe, request,
1208 [](const AtResponse& response) -> bool {
1209 return response.holds<CUSATE>();
1210 });
1211 if (!response || response->isParseError()) {
1212 status = FAILURE(RadioError::INTERNAL_ERR);
1213 } else if (const CUSATE* cusate = response->get_if<CUSATE>()) {
1214 commandResponse = cusate->response;
1215 } else {
1216 response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
1217 }
1218
1219 NOT_NULL(mRadioSimResponse)->sendEnvelopeResponse(
1220 makeRadioResponseInfo(serial, status), std::move(commandResponse));
1221 return status != RadioError::INTERNAL_ERR;
1222 });
1223
1224 return ScopedAStatus::ok();
1225 }
1226
sendEnvelopeWithStatus(const int32_t serial,const std::string &)1227 ScopedAStatus RadioSim::sendEnvelopeWithStatus(const int32_t serial,
1228 const std::string& /*contents*/) {
1229 NOT_NULL(mRadioSimResponse)->sendEnvelopeWithStatusResponse(
1230 makeRadioResponseInfoUnsupported( // matches reference-ril.c
1231 serial, FAILURE_DEBUG_PREFIX, __func__), {});
1232 return ScopedAStatus::ok();
1233 }
1234
sendTerminalResponseToSim(const int32_t serial,const std::string & commandResponse)1235 ScopedAStatus RadioSim::sendTerminalResponseToSim(const int32_t serial,
1236 const std::string& commandResponse) {
1237 static const char* const kFunc = __func__;
1238 mAtChannel->queueRequester([this, serial, commandResponse]
1239 (const AtChannel::RequestPipe requestPipe) -> bool {
1240 using CUSATT = AtResponse::CUSATT;
1241 RadioError status = RadioError::NONE;
1242
1243 const std::string request = std::format("AT+CUSATT=\"{0:s}\"", commandResponse);
1244 AtResponsePtr response =
1245 mAtConversation(requestPipe, request,
1246 [](const AtResponse& response) -> bool {
1247 return response.holds<CUSATT>();
1248 });
1249 if (!response || response->isParseError()) {
1250 status = FAILURE(RadioError::INTERNAL_ERR);
1251 } else if (!response->get_if<CUSATT>()) {
1252 response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
1253 }
1254
1255 NOT_NULL(mRadioSimResponse)->sendTerminalResponseToSimResponse(
1256 makeRadioResponseInfo(serial, status));
1257 return status != RadioError::INTERNAL_ERR;
1258 });
1259
1260 return ScopedAStatus::ok();
1261 }
1262
setAllowedCarriers(const int32_t serial,const sim::CarrierRestrictions &,const sim::SimLockMultiSimPolicy)1263 ScopedAStatus RadioSim::setAllowedCarriers(const int32_t serial,
1264 const sim::CarrierRestrictions& /*carriers*/,
1265 const sim::SimLockMultiSimPolicy /*multiSimPolicy*/) {
1266 NOT_NULL(mRadioSimResponse)->setAllowedCarriersResponse(
1267 makeRadioResponseInfoNOP(serial));
1268 return ScopedAStatus::ok();
1269 }
1270
setCarrierInfoForImsiEncryption(const int32_t serial,const sim::ImsiEncryptionInfo &)1271 ScopedAStatus RadioSim::setCarrierInfoForImsiEncryption(const int32_t serial,
1272 const sim::ImsiEncryptionInfo& /*imsiEncryptionInfo*/) {
1273 NOT_NULL(mRadioSimResponse)->setCarrierInfoForImsiEncryptionResponse(
1274 makeRadioResponseInfoUnsupported( // matches reference-ril.c
1275 serial, FAILURE_DEBUG_PREFIX, __func__));
1276 return ScopedAStatus::ok();
1277 }
1278
setCdmaSubscriptionSource(const int32_t serial,const sim::CdmaSubscriptionSource cdmaSub)1279 ScopedAStatus RadioSim::setCdmaSubscriptionSource(const int32_t serial,
1280 const sim::CdmaSubscriptionSource cdmaSub) {
1281 static const char* const kFunc = __func__;
1282 mAtChannel->queueRequester([this, serial, cdmaSub]
1283 (const AtChannel::RequestPipe requestPipe) -> bool {
1284 RadioError status = RadioError::NONE;
1285
1286 const std::string request =
1287 std::format("AT+CCSS={0:d}", static_cast<unsigned>(cdmaSub));
1288 const AtResponsePtr response =
1289 mAtConversation(requestPipe, request,
1290 [](const AtResponse& response) -> bool {
1291 return response.isOK();
1292 });
1293 if (!response || response->isParseError()) {
1294 status = FAILURE(RadioError::INTERNAL_ERR);
1295 } else if (!response->isOK()) {
1296 response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
1297 }
1298
1299 NOT_NULL(mRadioSimResponse)->setCdmaSubscriptionSourceResponse(
1300 makeRadioResponseInfo(serial, status));
1301 if ((status == RadioError::NONE) && mRadioSimIndication) {
1302 mRadioSimIndication->cdmaSubscriptionSourceChanged(
1303 RadioIndicationType::UNSOLICITED, cdmaSub);
1304 }
1305
1306 return status != RadioError::INTERNAL_ERR;
1307 });
1308
1309 return ScopedAStatus::ok();
1310 }
1311
setFacilityLockForApp(const int32_t serial,const std::string & facility,const bool lockState,const std::string & passwd,const int32_t serviceClass,const std::string &)1312 ScopedAStatus RadioSim::setFacilityLockForApp(const int32_t serial,
1313 const std::string& facility,
1314 const bool lockState,
1315 const std::string& passwd,
1316 const int32_t serviceClass,
1317 const std::string& /*appId*/) {
1318 static const char* const kFunc = __func__;
1319 mAtChannel->queueRequester([this, serial, facility, lockState,
1320 passwd, serviceClass]
1321 (const AtChannel::RequestPipe requestPipe) -> bool {
1322 using CmeError = AtResponse::CmeError;
1323
1324 RadioError status = RadioError::NONE;
1325 int retry = 1;
1326 const int lockStateInt = lockState ? 1 : 0;
1327
1328 std::string request;
1329 if (serviceClass == 0) {
1330 request = std::format("AT+CLCK=\"{0:s}\",{1:d},\"{2:s}\"",
1331 facility, lockStateInt, passwd);
1332 } else {
1333 request = std::format("AT+CLCK=\"{0:s}\",{1:d},\"{2:s}\",{3:d}",
1334 facility, lockStateInt, passwd, serviceClass);
1335 }
1336
1337 AtResponsePtr response =
1338 mAtConversation(requestPipe, request,
1339 [](const AtResponse& response) -> bool {
1340 return response.isOK() || response.holds<CmeError>();
1341 });
1342 if (!response || response->isParseError()) {
1343 status = FAILURE(RadioError::INTERNAL_ERR);
1344 } else if (response->get_if<CmeError>()) {
1345 if (facility.compare("SC"sv) == 0) {
1346 const std::optional<int> maybeRetries =
1347 getRemainingRetries("SIM PIN"sv, requestPipe, mAtConversation);
1348 if (maybeRetries) {
1349 status = FAILURE(RadioError::PASSWORD_INCORRECT);
1350 retry = maybeRetries.value();
1351 } else {
1352 status = FAILURE(RadioError::INTERNAL_ERR);
1353 }
1354 } else if (facility.compare("FD"sv) == 0) {
1355 const std::optional<int> maybeRetries =
1356 getRemainingRetries("SIM PIN2"sv, requestPipe, mAtConversation);
1357 if (maybeRetries) {
1358 status = FAILURE(RadioError::PASSWORD_INCORRECT);
1359 retry = maybeRetries.value();
1360 } else {
1361 status = FAILURE(RadioError::INTERNAL_ERR);
1362 }
1363 } else {
1364 status = FAILURE(RadioError::INVALID_ARGUMENTS);
1365 retry = -1;
1366 }
1367 } else if (!response->isOK()) {
1368 response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
1369 }
1370
1371 NOT_NULL(mRadioSimResponse)->setFacilityLockForAppResponse(
1372 makeRadioResponseInfo(serial, status), retry);
1373 return status != RadioError::INTERNAL_ERR;
1374 });
1375
1376 return ScopedAStatus::ok();
1377 }
1378
setSimCardPower(const int32_t serial,sim::CardPowerState)1379 ScopedAStatus RadioSim::setSimCardPower(const int32_t serial,
1380 sim::CardPowerState /*powerUp*/) {
1381 NOT_NULL(mRadioSimResponse)->setSimCardPowerResponse(
1382 makeRadioResponseInfoNOP(serial));
1383 return ScopedAStatus::ok();
1384 }
1385
setUiccSubscription(const int32_t serial,const sim::SelectUiccSub &)1386 ScopedAStatus RadioSim::setUiccSubscription(const int32_t serial,
1387 const sim::SelectUiccSub& /*uiccSub*/) {
1388 NOT_NULL(mRadioSimResponse)->setUiccSubscriptionResponse(
1389 makeRadioResponseInfoUnsupported( // matches reference-ril.c
1390 serial, FAILURE_DEBUG_PREFIX, __func__));
1391 return ScopedAStatus::ok();
1392 }
1393
supplyIccPin2ForApp(int32_t serial,const std::string & pin2,const std::string &)1394 ScopedAStatus RadioSim::supplyIccPin2ForApp(int32_t serial,
1395 const std::string& pin2,
1396 const std::string& /*aid*/) {
1397 mAtChannel->queueRequester([this, serial, pin2]
1398 (const AtChannel::RequestPipe requestPipe) -> bool {
1399 const auto [status, remainingRetries] =
1400 enterOrChangeSimPinPuk(false, pin2, "", "SIM PIN2"sv,
1401 requestPipe, mAtConversation);
1402
1403 NOT_NULL(mRadioSimResponse)->supplyIccPin2ForAppResponse(
1404 makeRadioResponseInfo(serial, status), remainingRetries);
1405 return status != RadioError::INTERNAL_ERR;
1406 });
1407
1408 return ScopedAStatus::ok();
1409 }
1410
supplyIccPinForApp(int32_t serial,const std::string & pin,const std::string &)1411 ScopedAStatus RadioSim::supplyIccPinForApp(int32_t serial,
1412 const std::string& pin,
1413 const std::string& /*aid*/) {
1414 mAtChannel->queueRequester([this, serial, pin]
1415 (const AtChannel::RequestPipe requestPipe) -> bool {
1416 const auto [status, remainingRetries] =
1417 enterOrChangeSimPinPuk(false, pin, "", "SIM PIN"sv,
1418 requestPipe, mAtConversation);
1419
1420 NOT_NULL(mRadioSimResponse)->supplyIccPinForAppResponse(
1421 makeRadioResponseInfo(serial, status), remainingRetries);
1422 return status != RadioError::INTERNAL_ERR;
1423 });
1424
1425 return ScopedAStatus::ok();
1426 }
1427
supplyIccPuk2ForApp(int32_t serial,const std::string & puk2,const std::string & pin2,const std::string &)1428 ScopedAStatus RadioSim::supplyIccPuk2ForApp(int32_t serial,
1429 const std::string& puk2,
1430 const std::string& pin2,
1431 const std::string& /*aid*/) {
1432 mAtChannel->queueRequester([this, serial, puk2, pin2]
1433 (const AtChannel::RequestPipe requestPipe) -> bool {
1434 const auto [status, remainingRetries] =
1435 enterOrChangeSimPinPuk(true, puk2, pin2, "SIM PUK2"sv,
1436 requestPipe, mAtConversation);
1437
1438 NOT_NULL(mRadioSimResponse)->supplyIccPuk2ForAppResponse(
1439 makeRadioResponseInfo(serial, status), remainingRetries);
1440 return status != RadioError::INTERNAL_ERR;
1441 });
1442
1443 return ScopedAStatus::ok();
1444 }
1445
supplyIccPukForApp(const int32_t serial,const std::string & puk,const std::string & pin,const std::string &)1446 ScopedAStatus RadioSim::supplyIccPukForApp(const int32_t serial,
1447 const std::string& puk,
1448 const std::string& pin,
1449 const std::string& /*aid*/) {
1450 mAtChannel->queueRequester([this, serial, puk, pin]
1451 (const AtChannel::RequestPipe requestPipe) -> bool {
1452 const auto [status, remainingRetries] =
1453 enterOrChangeSimPinPuk(true, puk, pin, "SIM PUK"sv,
1454 requestPipe, mAtConversation);
1455
1456 NOT_NULL(mRadioSimResponse)->supplyIccPukForAppResponse(
1457 makeRadioResponseInfo(serial, status), remainingRetries);
1458 return status != RadioError::INTERNAL_ERR;
1459 });
1460
1461 return ScopedAStatus::ok();
1462 }
1463
supplySimDepersonalization(const int32_t serial,sim::PersoSubstate,const std::string &)1464 ScopedAStatus RadioSim::supplySimDepersonalization(const int32_t serial,
1465 sim::PersoSubstate /*persoType*/,
1466 const std::string& /*controlKey*/) {
1467 NOT_NULL(mRadioSimResponse)->supplySimDepersonalizationResponse(
1468 makeRadioResponseInfoUnsupported( // matches reference-ril.c
1469 serial, FAILURE_DEBUG_PREFIX, __func__),
1470 {}, 0);
1471 return ScopedAStatus::ok();
1472 }
1473
updateSimPhonebookRecords(const int32_t serial,const sim::PhonebookRecordInfo &)1474 ScopedAStatus RadioSim::updateSimPhonebookRecords(const int32_t serial,
1475 const sim::PhonebookRecordInfo& /*recordInfo*/) {
1476 NOT_NULL(mRadioSimResponse)->updateSimPhonebookRecordsResponse(
1477 makeRadioResponseInfoUnsupported( // matches reference-ril.c
1478 serial, FAILURE_DEBUG_PREFIX, __func__), 0);
1479 return ScopedAStatus::ok();
1480 }
1481
handleUnsolicited(const AtResponse::CFUN & cfun)1482 void RadioSim::handleUnsolicited(const AtResponse::CFUN& cfun) {
1483 bool changed;
1484 {
1485 std::lock_guard<std::mutex> lock(mMtx);
1486 changed = mRadioState != cfun.state;
1487 mRadioState = cfun.state;
1488 }
1489
1490 if (changed && mRadioSimIndication) {
1491 mRadioSimIndication->simStatusChanged(
1492 RadioIndicationType::UNSOLICITED);
1493
1494 mRadioSimIndication->subscriptionStatusChanged(
1495 RadioIndicationType::UNSOLICITED, mRadioState == modem::RadioState::ON);
1496 }
1497 }
1498
handleUnsolicited(const AtResponse::CUSATP & cusatp)1499 void RadioSim::handleUnsolicited(const AtResponse::CUSATP& cusatp) {
1500 const std::string& cmd = cusatp.cmd;
1501 if (cmd.size() < 3) {
1502 return;
1503 }
1504 const unsigned typeOffset = (cmd[2] <= '7') ? 10 : 12;
1505 if (cmd.size() < (typeOffset + 2)) {
1506 return;
1507 }
1508
1509 unsigned cmdType = 0;
1510 if (!(std::from_chars(&cmd[typeOffset], &cmd[typeOffset + 2], cmdType, 16).ec == std::errc{})) {
1511 return;
1512 }
1513
1514 const StkCmdType stkCmdType = static_cast<StkCmdType>(cmdType);
1515
1516 enum class Action {
1517 NOTHING, NOTIFY, PROACTIVE_CMD
1518 };
1519
1520 Action action;
1521
1522 {
1523 std::lock_guard<std::mutex> lock(mMtx);
1524
1525 switch (stkCmdType) {
1526 case StkCmdType::RUN_AT:
1527 case StkCmdType::SEND_DTMF:
1528 case StkCmdType::SEND_SMS:
1529 case StkCmdType::SEND_SS:
1530 case StkCmdType::SEND_USSD:
1531 case StkCmdType::PLAY_TONE:
1532 case StkCmdType::CLOSE_CHANNEL:
1533 action = Action::NOTIFY;
1534 break;
1535
1536 case StkCmdType::REFRESH:
1537 if (cmd.size() >= (typeOffset + 4) && !strncmp(&cmd[typeOffset + 2], "04", 2)) {
1538 // SIM_RESET
1539 mStkServiceRunning = false;
1540 action = Action::NOTHING;
1541 } else {
1542 action = Action::NOTIFY;
1543 }
1544 break;
1545
1546 default:
1547 action = Action::PROACTIVE_CMD;
1548 break;
1549 }
1550
1551 if (!mStkServiceRunning) {
1552 mStkUnsolResponse = cusatp;
1553 action = Action::NOTHING;
1554 }
1555 }
1556
1557 if (mRadioSimIndication) {
1558 switch (action) {
1559 case Action::NOTIFY:
1560 mRadioSimIndication->stkEventNotify(RadioIndicationType::UNSOLICITED, cmd);
1561 break;
1562
1563 case Action::PROACTIVE_CMD:
1564 mRadioSimIndication->stkProactiveCommand(RadioIndicationType::UNSOLICITED, cmd);
1565 break;
1566
1567 case Action::NOTHING:
1568 break;
1569 }
1570 }
1571 }
1572
handleUnsolicited(const AtResponse::CUSATEND &)1573 void RadioSim::handleUnsolicited(const AtResponse::CUSATEND&) {
1574 if (mRadioSimIndication) {
1575 mRadioSimIndication->stkSessionEnd(RadioIndicationType::UNSOLICITED);
1576 }
1577 }
1578
atResponseSink(const AtResponsePtr & response)1579 void RadioSim::atResponseSink(const AtResponsePtr& response) {
1580 if (!mAtConversation.send(response)) {
1581 response->visit([this](const auto& msg){ handleUnsolicited(msg); });
1582 }
1583 }
1584
responseAcknowledgement()1585 ScopedAStatus RadioSim::responseAcknowledgement() {
1586 return ScopedAStatus::ok();
1587 }
1588
setResponseFunctions(const std::shared_ptr<sim::IRadioSimResponse> & radioSimResponse,const std::shared_ptr<sim::IRadioSimIndication> & radioSimIndication)1589 ScopedAStatus RadioSim::setResponseFunctions(
1590 const std::shared_ptr<sim::IRadioSimResponse>& radioSimResponse,
1591 const std::shared_ptr<sim::IRadioSimIndication>& radioSimIndication) {
1592 mRadioSimResponse = NOT_NULL(radioSimResponse);
1593 mRadioSimIndication = NOT_NULL(radioSimIndication);
1594 return ScopedAStatus::ok();
1595 }
1596
1597 /************************* deprecated *************************/
iccCloseLogicalChannel(const int32_t serial,const int32_t)1598 ScopedAStatus RadioSim::iccCloseLogicalChannel(const int32_t serial,
1599 const int32_t /*channelId*/) {
1600 NOT_NULL(mRadioSimResponse)->iccCloseLogicalChannelResponse(
1601 makeRadioResponseInfoDeprecated(serial));
1602 return ScopedAStatus::ok();
1603 }
1604
1605 } // namespace implementation
1606 } // namespace radio
1607 } // namespace hardware
1608 } // namespace android
1609 } // namespace aidl
1610