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 }
setEarlyBootEndedPending()48 void JavacardSecureElement::setEarlyBootEndedPending() {
49 isEarlyBootEndedPending = true;
50 }
sendPendingEvents()51 void JavacardSecureElement::sendPendingEvents() {
52 if (isDeleteAllKeysPending) {
53 auto [_, err] = sendRequest(Instruction::INS_DELETE_ALL_KEYS_CMD);
54 if (err == KM_ERROR_OK) {
55 isDeleteAllKeysPending = false;
56 } else {
57 LOG(ERROR) << "Error in sending deleteAllKeys.";
58 }
59 }
60 if (isEarlyBootEndedPending) {
61 auto [_, err] = sendRequest(Instruction::INS_EARLY_BOOT_ENDED_CMD);
62 if (err == KM_ERROR_OK) {
63 isEarlyBootEndedPending = false;
64 } else {
65 LOG(ERROR) << "Error in sending earlyBootEnded.";
66 }
67 }
68 }
69
constructApduMessage(Instruction & ins,std::vector<uint8_t> & inputData,std::vector<uint8_t> & apduOut)70 keymaster_error_t JavacardSecureElement::constructApduMessage(Instruction& ins,
71 std::vector<uint8_t>& inputData,
72 std::vector<uint8_t>& apduOut) {
73 apduOut.push_back(static_cast<uint8_t>(APDU_CLS)); // CLS
74 apduOut.push_back(static_cast<uint8_t>(ins)); // INS
75 apduOut.push_back(static_cast<uint8_t>(APDU_P1)); // P1
76 apduOut.push_back(static_cast<uint8_t>(APDU_P2)); // P2
77
78 if (USHRT_MAX >= inputData.size()) {
79 // Send extended length APDU always as response size is not known to HAL.
80 // Case 1: Lc > 0 CLS | INS | P1 | P2 | 00 | 2 bytes of Lc | CommandData |
81 // 2 bytes of Le all set to 00. Case 2: Lc = 0 CLS | INS | P1 | P2 | 3
82 // bytes of Le all set to 00. Extended length 3 bytes, starts with 0x00
83 apduOut.push_back(static_cast<uint8_t>(0x00));
84 if (inputData.size() > 0) {
85 apduOut.push_back(static_cast<uint8_t>(inputData.size() >> 8));
86 apduOut.push_back(static_cast<uint8_t>(inputData.size() & 0xFF));
87 // Data
88 apduOut.insert(apduOut.end(), inputData.begin(), inputData.end());
89 }
90 // Expected length of output.
91 // Accepting complete length of output every time.
92 apduOut.push_back(static_cast<uint8_t>(0x00));
93 apduOut.push_back(static_cast<uint8_t>(0x00));
94 } else {
95 LOG(ERROR) << "Error in constructApduMessage.";
96 return (KM_ERROR_INVALID_INPUT_LENGTH);
97 }
98 return (KM_ERROR_OK); // success
99 }
100
sendData(Instruction ins,std::vector<uint8_t> & inData,std::vector<uint8_t> & response)101 keymaster_error_t JavacardSecureElement::sendData(Instruction ins, std::vector<uint8_t>& inData,
102 std::vector<uint8_t>& response) {
103 keymaster_error_t ret = KM_ERROR_UNKNOWN_ERROR;
104 std::vector<uint8_t> apdu;
105
106 ret = constructApduMessage(ins, inData, apdu);
107
108 if (ret != KM_ERROR_OK) {
109 return ret;
110 }
111
112 if (!transport_->sendData(apdu, response)) {
113 LOG(ERROR) << "Error in sending data in sendData.";
114 return (KM_ERROR_SECURE_HW_COMMUNICATION_FAILED);
115 }
116
117 // Response size should be greater than 2. Cbor output data followed by two
118 // bytes of APDU status.
119 if ((response.size() <= 2) || (getApduStatus(response) != APDU_RESP_STATUS_OK)) {
120 LOG(ERROR) << "Response of the sendData is wrong: response size = " << response.size()
121 << " apdu status = " << getApduStatus(response);
122 return (KM_ERROR_UNKNOWN_ERROR);
123 }
124 // remove the status bytes
125 response.pop_back();
126 response.pop_back();
127 return (KM_ERROR_OK); // success
128 }
129
130 std::tuple<std::unique_ptr<Item>, keymaster_error_t>
sendRequest(Instruction ins,Array & request)131 JavacardSecureElement::sendRequest(Instruction ins, Array& request) {
132 vector<uint8_t> response;
133 // encode request
134 std::vector<uint8_t> command = request.encode();
135 auto sendError = sendData(ins, command, response);
136 if (sendError != KM_ERROR_OK) {
137 return {unique_ptr<Item>(nullptr), sendError};
138 }
139 // decode the response and send that back
140 return cbor_.decodeData(response);
141 }
142
143 std::tuple<std::unique_ptr<Item>, keymaster_error_t>
sendRequest(Instruction ins,std::vector<uint8_t> & command)144 JavacardSecureElement::sendRequest(Instruction ins, std::vector<uint8_t>& command) {
145 vector<uint8_t> response;
146 auto sendError = sendData(ins, command, response);
147 if (sendError != KM_ERROR_OK) {
148 return {unique_ptr<Item>(nullptr), sendError};
149 }
150 // decode the response and send that back
151 return cbor_.decodeData(response);
152 }
153
154 std::tuple<std::unique_ptr<Item>, keymaster_error_t>
sendRequest(Instruction ins)155 JavacardSecureElement::sendRequest(Instruction ins) {
156 vector<uint8_t> response;
157 vector<uint8_t> emptyRequest;
158 auto sendError = sendData(ins, emptyRequest, response);
159 if (sendError != KM_ERROR_OK) {
160 return {unique_ptr<Item>(nullptr), sendError};
161 }
162 // decode the response and send that back
163 return cbor_.decodeData(response);
164 }
165
166 } // namespace keymint::javacard
167