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