• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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