1 /******************************************************************************
2 *
3 * Copyright 2021-2023 NXP
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18 #define LOG_TAG "SBAccessController"
19
20 #include <android-base/logging.h>
21 #include <map>
22 #include <vector>
23
24 #include <EseTransportUtils.h>
25 #include <SBAccessController.h>
26
27 #define UPGRADE_OFFSET_SW 3 // upgrade offset from last in response
28 #define UPGRADE_MASK_BIT 0x02 // Update bit mask in upgrade byte
29 #define UPGRADE_MASK_VAL 0x02 // Update mask value in upgrade byte
30
31 namespace keymint::javacard {
32
33 static bool g_AccessAllowed = true;
34 static bool g_IsCryptoOperationRunning = false;
35
36 // These should be in sync with JavacardKeymasterDevice41.cpp
37 // Allow listed cmds
38 std::map<uint8_t, uint8_t> allowedCmdIns = {{0xD9 /*INS_SET_VERSION_PATCHLEVEL*/, 0},
39 {0x2A /*INS_COMPUTE_SHARED_HMAC*/, 0},
40 {0x2D /*INS_GET_HMAC_SHARING_PARAM*/, 0}};
41
CryptoOpTimerFunc(union sigval arg)42 static void CryptoOpTimerFunc(union sigval arg) {
43 (void)arg; // unused
44 LOG(DEBUG) << "CryptoOperation timer expired";
45 g_IsCryptoOperationRunning = false;
46 }
47
AccessTimerFunc(union sigval arg)48 static void AccessTimerFunc(union sigval arg) {
49 (void)arg; // unused
50 LOG(DEBUG) << "Applet access-block timer expired";
51 g_AccessAllowed = true;
52 }
53
startTimer(bool isStart,IntervalTimer & t,int timeout,void (* timerFunc)(union sigval))54 void SBAccessController::startTimer(bool isStart, IntervalTimer& t, int timeout,
55 void (*timerFunc)(union sigval)) {
56 t.kill();
57 if (isStart) {
58 t.set(timeout, this, timerFunc);
59 }
60 }
61
parseResponse(std::vector<uint8_t> & responseApdu)62 void SBAccessController::parseResponse(std::vector<uint8_t>& responseApdu) {
63 // check if StrongBox Applet update is underway
64 if ((responseApdu[responseApdu.size() - UPGRADE_OFFSET_SW] & UPGRADE_MASK_BIT) ==
65 UPGRADE_MASK_VAL) {
66 mIsUpdateInProgress = true;
67 LOG(INFO) << "StrongBox Applet update is in progress";
68 g_AccessAllowed = false; // No access or Limited access
69 startTimer(true, mTimer, SB_ACCESS_BLOCK_TIMER, AccessTimerFunc);
70 } else {
71 mIsUpdateInProgress = false;
72 g_AccessAllowed = true; // Full access
73 startTimer(false, mTimer, 0, nullptr);
74 }
75 }
getSessionTimeout()76 int SBAccessController::getSessionTimeout() {
77 if (mIsUpdateInProgress) {
78 return (mBootState == BOOTSTATE::SB_EARLY_BOOT_ENDED) ? SMALLEST_SESSION_TIMEOUT
79 : UPGRADE_SESSION_TIMEOUT;
80 } else {
81 return g_IsCryptoOperationRunning ? CRYPTO_OP_SESSION_TIMEOUT : REGULAR_SESSION_TIMEOUT;
82 }
83 }
isSelectAllowed()84 bool SBAccessController::isSelectAllowed() {
85 bool select_allowed = false;
86 if (g_AccessAllowed) {
87 select_allowed = true;
88 } else {
89 switch (mBootState) {
90 case BOOTSTATE::SB_EARLY_BOOT:
91 select_allowed = true;
92 break;
93 case BOOTSTATE::SB_EARLY_BOOT_ENDED:
94 break;
95 }
96 }
97 if(!select_allowed)
98 LOG(INFO) << "StrongBox Applet selection is not allowed";
99
100 return select_allowed;
101 }
updateBootState()102 void SBAccessController::updateBootState() {
103 // set the state to BOOT_ENDED once we have received
104 // all allowed commands
105 bool allCmdreceived = true;
106 for (auto it = allowedCmdIns.begin(); it != allowedCmdIns.end(); it++) {
107 if (it->second == 0) {
108 allCmdreceived = false;
109 break;
110 }
111 }
112 if (allCmdreceived) {
113 LOG(INFO) << "All allowlisted cmds received , mark Early boot completed";
114 mBootState = BOOTSTATE::SB_EARLY_BOOT_ENDED;
115 }
116 }
isOperationAllowed(uint8_t cmdIns)117 bool SBAccessController::isOperationAllowed(uint8_t cmdIns) {
118 bool op_allowed = false;
119 if (g_AccessAllowed) {
120 op_allowed = true;
121 if (cmdIns == BEGIN_OPERATION_CMD) {
122 g_IsCryptoOperationRunning = true;
123 startTimer(true, mTimerCrypto, CRYPTO_OP_SESSION_TIMEOUT, CryptoOpTimerFunc);
124 } else if (cmdIns == FINISH_OPERATION_CMD || cmdIns == ABORT_OPERATION_CMD) {
125 g_IsCryptoOperationRunning = false;
126 startTimer(false, mTimerCrypto, 0, nullptr);
127 }
128 } else {
129 switch (mBootState) {
130 case BOOTSTATE::SB_EARLY_BOOT: {
131 auto it = allowedCmdIns.find(cmdIns);
132 if (it != allowedCmdIns.end()) {
133 it->second = 1; // cmd received
134 updateBootState();
135 op_allowed = true;
136 }
137 } break;
138 case BOOTSTATE::SB_EARLY_BOOT_ENDED:
139 break;
140 }
141 }
142 if (cmdIns == EARLY_BOOT_ENDED_CMD) {
143 // allowed as this is sent by VOLD only during early boot
144 op_allowed = true;
145 }
146 return op_allowed;
147 }
148 } // namespace keymint::javacard
149