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