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 2023-2024 NXP
33  *
34  ******************************************************************************/
35 
36 #define LOG_TAG "javacard.keymint.device.strongbox-impl"
37 #include "JavacardSecureElement.h"
38 #include "keymint_utils.h"
39 
40 #include <algorithm>
41 #include <android-base/logging.h>
42 #include <android-base/properties.h>
43 #include <iostream>
44 #include <iterator>
45 #include <keymaster/android_keymaster_messages.h>
46 #include <memory>
47 #include <regex.h>
48 #include <string>
49 #include <vector>
50 
51 namespace keymint::javacard {
52 
initializeJavacard()53 keymaster_error_t JavacardSecureElement::initializeJavacard() {
54     keymaster_error_t ret = KM_ERROR_OK;
55     if (!isCardInitialized_) {
56         Array request;
57         request.add(Uint(getOsVersion()));
58         request.add(Uint(getOsPatchlevel()));
59         request.add(Uint(getVendorPatchlevel()));
60         auto [item, err] = sendRequest(Instruction::INS_SET_BOOT_PARAMS_CMD, request);
61         if (err == KM_ERROR_OK) {
62             isCardInitialized_ = true;
63         }
64         ret = err;
65     }
66     return ret;
67 }
68 
constructApduMessage(Instruction & ins,std::vector<uint8_t> & inputData,std::vector<uint8_t> & apduOut)69 keymaster_error_t JavacardSecureElement::constructApduMessage(Instruction& ins,
70                                                               std::vector<uint8_t>& inputData,
71                                                               std::vector<uint8_t>& apduOut) {
72     apduOut.push_back(static_cast<uint8_t>(APDU_CLS));  // CLS
73     apduOut.push_back(static_cast<uint8_t>(ins));       // INS
74     apduOut.push_back(static_cast<uint8_t>(APDU_P1));   // P1
75     apduOut.push_back(static_cast<uint8_t>(APDU_P2));   // P2
76 
77     if (USHRT_MAX >= inputData.size()) {
78         // Send extended length APDU always as response size is not known to HAL.
79         // Case 1: Lc > 0  CLS | INS | P1 | P2 | 00 | 2 bytes of Lc | CommandData | 2 bytes of Le
80         // all set to 00. Case 2: Lc = 0  CLS | INS | P1 | P2 | 3 bytes of Le all set to 00.
81         // Extended length 3 bytes, starts with 0x00
82         apduOut.push_back(static_cast<uint8_t>(0x00));
83         if (inputData.size() > 0) {
84             apduOut.push_back(static_cast<uint8_t>(inputData.size() >> 8));
85             apduOut.push_back(static_cast<uint8_t>(inputData.size() & 0xFF));
86             // Data
87             apduOut.insert(apduOut.end(), inputData.begin(), inputData.end());
88         }
89         // Expected length of output.
90         // Accepting complete length of output every time.
91         apduOut.push_back(static_cast<uint8_t>(0x00));
92         apduOut.push_back(static_cast<uint8_t>(0x00));
93     } else {
94         LOG(ERROR) << "Error in constructApduMessage.";
95         return (KM_ERROR_INVALID_INPUT_LENGTH);
96     }
97     return (KM_ERROR_OK);  // success
98 }
99 
sendData(Instruction ins,std::vector<uint8_t> & inData,std::vector<uint8_t> & response)100 keymaster_error_t JavacardSecureElement::sendData(Instruction ins, std::vector<uint8_t>& inData,
101                                                   std::vector<uint8_t>& response) {
102     keymaster_error_t ret = KM_ERROR_UNKNOWN_ERROR;
103     std::vector<uint8_t> apdu;
104 
105     ret = constructApduMessage(ins, inData, apdu);
106 
107     if (ret != KM_ERROR_OK) {
108         return ret;
109     }
110 
111     if (!transport_->sendData(apdu, response) && (response.size() < 2)) {
112         LOG(ERROR) << "Error in sending C-APDU";
113         return (KM_ERROR_SECURE_HW_COMMUNICATION_FAILED);
114     }
115     // Response size should be greater than 2. Cbor output data followed by two
116     // bytes of APDU status.
117     if (getApduStatus(response) != APDU_RESP_STATUS_OK) {
118         LOG(ERROR) << "ERROR Response apdu status = " << std::uppercase << std::hex
119                    << getApduStatus(response);
120         return (KM_ERROR_UNKNOWN_ERROR);
121     }
122     // remove the status bytes
123     response.pop_back();
124     response.pop_back();
125     return (KM_ERROR_OK);  // success
126 }
127 
128 std::tuple<std::unique_ptr<Item>, keymaster_error_t>
sendRequest(Instruction ins,Array & request)129 JavacardSecureElement::sendRequest(Instruction ins, Array& request) {
130     vector<uint8_t> response;
131     // encode request
132     std::vector<uint8_t> command = request.encode();
133     auto sendError = sendData(ins, command, response);
134     if (sendError != KM_ERROR_OK) {
135         return {unique_ptr<Item>(nullptr), sendError};
136     }
137     // decode the response and send that back
138     return cbor_.decodeData(response);
139 }
140 
141 std::tuple<std::unique_ptr<Item>, keymaster_error_t>
sendRequest(Instruction ins,std::vector<uint8_t> & command)142 JavacardSecureElement::sendRequest(Instruction ins, std::vector<uint8_t>& command) {
143     vector<uint8_t> response;
144     auto sendError = sendData(ins, command, response);
145     if (sendError != KM_ERROR_OK) {
146         return {unique_ptr<Item>(nullptr), sendError};
147     }
148     // decode the response and send that back
149     return cbor_.decodeData(response);
150 }
151 
152 std::tuple<std::unique_ptr<Item>, keymaster_error_t>
sendRequest(Instruction ins)153 JavacardSecureElement::sendRequest(Instruction ins) {
154     vector<uint8_t> response;
155     vector<uint8_t> emptyRequest;
156     auto sendError = sendData(ins, emptyRequest, response);
157     if (sendError != KM_ERROR_OK) {
158         return {unique_ptr<Item>(nullptr), sendError};
159     }
160     // decode the response and send that back
161     return cbor_.decodeData(response);
162 }
163 
164 #ifdef NXP_EXTNS
setOperationState(CryptoOperationState state)165 void JavacardSecureElement::setOperationState(CryptoOperationState state) {
166     transport_->setCryptoOperationState(state);
167 }
168 #endif
169 
170 }  // namespace keymint::javacard
171