1 /*
2  * Copyright 2020, 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 *
18 *  The original Work has been changed by NXP.
19 *
20 *  Licensed under the Apache License, Version 2.0 (the "License");
21 *  you may not use this file except in compliance with the License.
22 *  You may obtain a copy of the License at
23 *
24 *  http://www.apache.org/licenses/LICENSE-2.0
25 *
26 *  Unless required by applicable law or agreed to in writing, software
27 *  distributed under the License is distributed on an "AS IS" BASIS,
28 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
29 *  See the License for the specific language governing permissions and
30 *  limitations under the License.
31 *
32 *  Copyright 2024 NXP
33 *
34 ******************************************************************************/
35 
36 #define LOG_TAG "javacard.keymint.device.strongbox-impl"
37 #include "JavacardSecureElement.h"
38 
39 #include <algorithm>
40 #include <iostream>
41 #include <iterator>
42 #include <memory>
43 #include <regex.h>
44 #include <string>
45 #include <vector>
46 
47 #ifdef INIT_USING_SEHAL_TRANSPORT
48 #include <HalToHalTransport.h>
49 #endif
50 #include <aidl/android/hardware/security/keymint/ErrorCode.h>
51 #include <android-base/logging.h>
52 #include <android-base/properties.h>
53 #include <keymaster/android_keymaster_messages.h>
54 
55 #include "keymint_utils.h"
56 
57 namespace keymint::javacard {
58 using ::aidl::android::hardware::security::keymint::ErrorCode;
59 const std::vector<uint8_t> gStrongBoxAppletAID = {0xA0, 0x00, 0x00, 0x00, 0x62};
60 
61 namespace {
aidlEnumErrorCode2km(ErrorCode err)62 keymaster_error_t aidlEnumErrorCode2km(ErrorCode err) {
63     return static_cast<keymaster_error_t>(err);
64 }
65 }  // namespace
66 
initializeJavacard()67 keymaster_error_t JavacardSecureElement::initializeJavacard() {
68     Array request;
69     request.add(Uint(getOsVersion()));
70     request.add(Uint(getOsPatchlevel()));
71     request.add(Uint(getVendorPatchlevel()));
72     auto [item, err] = sendRequest(Instruction::INS_INIT_STRONGBOX_CMD, request);
73     return err;
74 }
75 
setDeleteAllKeysPending()76 void JavacardSecureElement::setDeleteAllKeysPending() {
77     isDeleteAllKeysPending = true;
78 }
setEarlyBootEndedPending()79 void JavacardSecureElement::setEarlyBootEndedPending() {
80     isEarlyBootEndedPending = true;
81 }
sendPendingEvents()82 void JavacardSecureElement::sendPendingEvents() {
83     if (isCardInitPending) {
84         if (KM_ERROR_OK == initializeJavacard()) {
85             isCardInitPending = false;
86         } else {
87             LOG(ERROR) << "Error in sending system properties(OS_VERSION, OS_PATCH, VENDOR_PATCH).";
88         }
89     }
90 
91     if (isDeleteAllKeysPending) {
92         auto [_, err] = sendRequest(Instruction::INS_DELETE_ALL_KEYS_CMD);
93         if (err == KM_ERROR_OK) {
94             isDeleteAllKeysPending = false;
95         } else {
96             LOG(ERROR) << "Error in sending deleteAllKeys.";
97         }
98     }
99     if (isEarlyBootEndedPending) {
100         auto [_, err] = sendRequest(Instruction::INS_EARLY_BOOT_ENDED_CMD);
101         if (err == KM_ERROR_OK) {
102             isEarlyBootEndedPending = false;
103         } else {
104             LOG(ERROR) << "Error in sending earlyBootEnded.";
105         }
106     }
107 }
108 
constructApduMessage(Instruction & ins,const std::vector<uint8_t> & inputData,std::vector<uint8_t> & apduOut)109 keymaster_error_t JavacardSecureElement::constructApduMessage(Instruction& ins,
110                                                               const std::vector<uint8_t>& inputData,
111                                                               std::vector<uint8_t>& apduOut) {
112     apduOut.push_back(static_cast<uint8_t>(APDU_CLS));  // CLS
113     apduOut.push_back(static_cast<uint8_t>(ins));       // INS
114     apduOut.push_back(static_cast<uint8_t>(APDU_P1));   // P1
115     apduOut.push_back(static_cast<uint8_t>(APDU_P2));   // P2
116 
117     if (USHRT_MAX >= inputData.size()) {
118         // Send extended length APDU always as response size is not known to HAL.
119         // Case 1: Lc > 0  CLS | INS | P1 | P2 | 00 | 2 bytes of Lc | CommandData |
120         // 2 bytes of Le all set to 00. Case 2: Lc = 0  CLS | INS | P1 | P2 | 3
121         // bytes of Le all set to 00. Extended length 3 bytes, starts with 0x00
122         apduOut.push_back(static_cast<uint8_t>(0x00));
123         if (inputData.size() > 0) {
124             apduOut.push_back(static_cast<uint8_t>(inputData.size() >> 8));
125             apduOut.push_back(static_cast<uint8_t>(inputData.size() & 0xFF));
126             // Data
127             apduOut.insert(apduOut.end(), inputData.begin(), inputData.end());
128         }
129         // Expected length of output.
130         // Accepting complete length of output every time.
131         apduOut.push_back(static_cast<uint8_t>(0x00));
132         apduOut.push_back(static_cast<uint8_t>(0x00));
133     } else {
134         LOG(ERROR) << "Error in constructApduMessage.";
135         return (KM_ERROR_INVALID_INPUT_LENGTH);
136     }
137     return (KM_ERROR_OK);  // success
138 }
139 
sendData(const std::shared_ptr<ITransport> & transport,Instruction ins,const std::vector<uint8_t> & inData,std::vector<uint8_t> & response)140 keymaster_error_t JavacardSecureElement::sendData(const std::shared_ptr<ITransport>& transport,
141                                                   Instruction ins,
142                                                   const std::vector<uint8_t>& inData,
143                                                   std::vector<uint8_t>& response) {
144     keymaster_error_t ret = KM_ERROR_UNKNOWN_ERROR;
145     std::vector<uint8_t> apdu;
146 
147     ret = constructApduMessage(ins, inData, apdu);
148 
149     if (ret != KM_ERROR_OK) {
150         return ret;
151     }
152 
153     if (!transport->sendData(apdu, response) && (response.size() < 2)) {
154         LOG(ERROR) << "Error in sending C-APDU";
155         return (KM_ERROR_SECURE_HW_COMMUNICATION_FAILED);
156     }
157     // Response size should be greater than 2. Cbor output data followed by two
158     // bytes of APDU status.
159     if (getApduStatus(response) != APDU_RESP_STATUS_OK) {
160         LOG(ERROR) << "ERROR Response apdu status = " << std::uppercase << std::hex
161                    << getApduStatus(response);
162         return (KM_ERROR_UNKNOWN_ERROR);
163     }
164     // remove the status bytes
165     response.pop_back();
166     response.pop_back();
167     return (KM_ERROR_OK);  // success
168 }
169 
sendData(Instruction ins,const std::vector<uint8_t> & inData,std::vector<uint8_t> & response)170 keymaster_error_t JavacardSecureElement::sendData(Instruction ins,
171                                                   const std::vector<uint8_t>& inData,
172                                                   std::vector<uint8_t>& response) {
173     return sendData(transport_, ins, inData, response);
174 }
175 
sendRequest(Instruction ins,const Array & request)176 std::tuple<std::unique_ptr<Item>, keymaster_error_t> JavacardSecureElement::sendRequest(
177     Instruction ins, const Array& request) {
178     return sendRequest(transport_, ins, request.encode());
179 }
180 
sendRequest(Instruction ins,const std::vector<uint8_t> & command)181 std::tuple<std::unique_ptr<Item>, keymaster_error_t> JavacardSecureElement::sendRequest(
182     Instruction ins, const std::vector<uint8_t>& command) {
183     return sendRequest(transport_, ins, command);
184 }
185 
sendRequest(Instruction ins)186 std::tuple<std::unique_ptr<Item>, keymaster_error_t> JavacardSecureElement::sendRequest(
187     Instruction ins) {
188     return sendRequest(transport_, ins, std::vector<uint8_t>());
189 }
190 #ifdef INIT_USING_SEHAL_TRANSPORT
initSEHal()191 bool JavacardSecureElement::initSEHal() {
192     if (seHalTransport == nullptr) {
193         seHalTransport = std::make_shared<HalToHalTransport>(gStrongBoxAppletAID);
194     }
195     return seHalTransport->openConnection();
196 }
197 
closeSEHal()198 bool JavacardSecureElement::closeSEHal() {
199     bool ret = true;
200     if (seHalTransport != nullptr) {
201         ret = seHalTransport->closeConnection();
202         if (!ret) {
203             LOG(INFO) << "Failed to close SE Hal.";
204         }
205         seHalTransport = nullptr;
206     }
207     return ret;
208 }
209 #endif
sendRequestSeHal(Instruction ins,const std::vector<uint8_t> & command)210 std::tuple<std::unique_ptr<Item>, keymaster_error_t> JavacardSecureElement::sendRequestSeHal(
211     Instruction ins, const std::vector<uint8_t>& command) {
212     if (seHalTransport != nullptr) {
213         return sendRequest(seHalTransport, ins, command);
214     } else {
215         auto [item, err] = sendRequest(ins, command);
216         if (err != KM_ERROR_OK) {
217 #ifdef INIT_USING_SEHAL_TRANSPORT
218             if (err == aidlEnumErrorCode2km(ErrorCode::SECURE_HW_COMMUNICATION_FAILED)) {
219                 LOG(DEBUG) << "OMAPI is not yet available. Send INS: " << static_cast<int>(ins)
220                            << " via SE Hal.";
221                 if (initSEHal()) {
222                     return sendRequest(seHalTransport, ins, command);
223                 }
224                 LOG(ERROR) << "Failed to initialize SE HAL";
225             }
226 #endif
227         }
228         return {std::move(item), std::move(err)};
229     }
230 }
231 
sendRequestSeHal(Instruction ins)232 std::tuple<std::unique_ptr<Item>, keymaster_error_t> JavacardSecureElement::sendRequestSeHal(
233     Instruction ins) {
234     return sendRequestSeHal(ins, std::vector<uint8_t>());
235 }
236 
sendRequest(const std::shared_ptr<ITransport> & transport,Instruction ins,const std::vector<uint8_t> & command)237 std::tuple<std::unique_ptr<Item>, keymaster_error_t> JavacardSecureElement::sendRequest(
238     const std::shared_ptr<ITransport>& transport, Instruction ins,
239     const std::vector<uint8_t>& command) {
240     vector<uint8_t> response;
241     auto sendError = sendData(transport, ins, command, response);
242     if (sendError != KM_ERROR_OK) {
243         return {unique_ptr<Item>(nullptr), sendError};
244     }
245     // decode the response and send that back
246     return cbor_.decodeData(response);
247 }
248 #ifdef NXP_EXTNS
setOperationState(CryptoOperationState state)249 void JavacardSecureElement::setOperationState(CryptoOperationState state) {
250     transport_->setCryptoOperationState(state);
251 }
252 #endif
253 }  // namespace keymint::javacard
254