1 /*
2 * Copyright 2021, 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 #define LOG_TAG "javacard.keymint.device.rkp.strongbox-impl"
36
37 #include "JavacardRemotelyProvisionedComponentDevice.h"
38
39 #include <aidl/android/hardware/security/keymint/MacedPublicKey.h>
40
41 #include <KeyMintUtils.h>
42 #include <android-base/logging.h>
43 #include <keymaster/cppcose/cppcose.h>
44 #include <keymaster/remote_provisioning_utils.h>
45
46 #include <memunreachable/memunreachable.h>
47
48 namespace aidl::android::hardware::security::keymint {
49 using cppbor::Array;
50 using cppbor::EncodedItem;
51 using cppcose::kCoseMac0EntryCount;
52 using cppcose::kCoseMac0Payload;
53 using ::keymint::javacard::Instruction;
54 using std::string;
55
56 // RKP error codes defined in keymint applet.
57 constexpr int32_t kStatusFailed = 32000;
58 constexpr int32_t kStatusInvalidMac = 32001;
59 constexpr int32_t kStatusProductionKeyInTestRequest = 32002;
60 constexpr int32_t kStatusTestKeyInProductionRequest = 32003;
61 constexpr int32_t kStatusInvalidEek = 32004;
62 constexpr int32_t kStatusInvalidState = 32005;
63
64 namespace {
65
translateRkpErrorCode(keymaster_error_t error)66 keymaster_error_t translateRkpErrorCode(keymaster_error_t error) {
67 switch (static_cast<int32_t>(-error)) {
68 case kStatusFailed:
69 case kStatusInvalidState:
70 return static_cast<keymaster_error_t>(BnRemotelyProvisionedComponent::STATUS_FAILED);
71 case kStatusInvalidMac:
72 return static_cast<keymaster_error_t>(BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
73 case kStatusProductionKeyInTestRequest:
74 return static_cast<keymaster_error_t>(
75 BnRemotelyProvisionedComponent::STATUS_PRODUCTION_KEY_IN_TEST_REQUEST);
76 case kStatusTestKeyInProductionRequest:
77 return static_cast<keymaster_error_t>(
78 BnRemotelyProvisionedComponent::STATUS_TEST_KEY_IN_PRODUCTION_REQUEST);
79 case kStatusInvalidEek:
80 return static_cast<keymaster_error_t>(BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
81 }
82 return error;
83 }
84
defaultHwInfo(RpcHardwareInfo * info)85 ScopedAStatus defaultHwInfo(RpcHardwareInfo* info) {
86 info->versionNumber = 3;
87 info->rpcAuthorName = "Google";
88 info->supportedEekCurve = RpcHardwareInfo::CURVE_NONE;
89 info->uniqueId = "Google Strongbox KeyMint 3";
90 info->supportedNumKeysInCsr = RpcHardwareInfo::MIN_SUPPORTED_NUM_KEYS_IN_CSR;
91 return ScopedAStatus::ok();
92 }
93
coseKeyEncodedSize(const std::vector<MacedPublicKey> & keysToSign)94 uint32_t coseKeyEncodedSize(const std::vector<MacedPublicKey>& keysToSign) {
95 uint32_t size = 0;
96 for (auto& macKey : keysToSign) {
97 auto [macedKeyItem, _, coseMacErrMsg] = cppbor::parse(macKey.macedKey);
98 if (!macedKeyItem || !macedKeyItem->asArray() ||
99 macedKeyItem->asArray()->size() != kCoseMac0EntryCount) {
100 LOG(ERROR) << "Invalid COSE_Mac0 structure";
101 return 0;
102 }
103 auto payload = macedKeyItem->asArray()->get(kCoseMac0Payload)->asBstr();
104 if (!payload) return 0;
105 size += payload->value().size();
106 }
107 return size;
108 }
109
110 } // namespace
111
getHardwareInfo(RpcHardwareInfo * info)112 ScopedAStatus JavacardRemotelyProvisionedComponentDevice::getHardwareInfo(RpcHardwareInfo* info) {
113 auto [item, err] = card_->sendRequest(Instruction::INS_GET_RKP_HARDWARE_INFO);
114 std::optional<uint64_t> optVersionNumber;
115 std::optional<uint64_t> optSupportedEekCurve;
116 std::optional<string> optRpcAuthorName;
117 std::optional<string> optUniqueId;
118 std::optional<uint64_t> optMinSupportedKeysInCsr;
119 if (err != KM_ERROR_OK || !(optVersionNumber = cbor_.getUint64(item, 1)) ||
120 !(optRpcAuthorName = cbor_.getByteArrayStr(item, 2)) ||
121 !(optSupportedEekCurve = cbor_.getUint64(item, 3)) ||
122 !(optUniqueId = cbor_.getByteArrayStr(item, 4)) ||
123 !(optMinSupportedKeysInCsr = cbor_.getUint64(item, 5))) {
124 LOG(ERROR) << "Error in response of getHardwareInfo.";
125 LOG(INFO) << "Returning defaultHwInfo in getHardwareInfo.";
126 return defaultHwInfo(info);
127 }
128 card_->sendPendingEvents();
129 info->rpcAuthorName = std::move(optRpcAuthorName.value());
130 info->versionNumber = static_cast<int32_t>(std::move(optVersionNumber.value()));
131 info->supportedEekCurve = static_cast<int32_t>(std::move(optSupportedEekCurve.value()));
132 info->uniqueId = std::move(optUniqueId.value());
133 info->supportedNumKeysInCsr = static_cast<int32_t>(std::move(optMinSupportedKeysInCsr.value()));
134 return ScopedAStatus::ok();
135 }
136
generateEcdsaP256KeyPair(bool testMode,MacedPublicKey * macedPublicKey,std::vector<uint8_t> * privateKeyHandle)137 ScopedAStatus JavacardRemotelyProvisionedComponentDevice::generateEcdsaP256KeyPair(
138 bool testMode, MacedPublicKey* macedPublicKey, std::vector<uint8_t>* privateKeyHandle) {
139 if (testMode) {
140 return km_utils::kmError2ScopedAStatus(static_cast<keymaster_error_t>(STATUS_REMOVED));
141 }
142 card_->sendPendingEvents();
143 auto [item, err] = card_->sendRequest(Instruction::INS_GENERATE_RKP_KEY_CMD);
144 if (err != KM_ERROR_OK) {
145 LOG(ERROR) << "Error in sending generateEcdsaP256KeyPair.";
146 return km_utils::kmError2ScopedAStatus(translateRkpErrorCode(err));
147 }
148 std::optional<std::vector<uint8_t>> optMacedKey;
149 std::optional<std::vector<uint8_t>> optPKeyHandle;
150 if (!(optMacedKey = cbor_.getByteArrayVec(item, 1)) ||
151 !(optPKeyHandle = cbor_.getByteArrayVec(item, 2))) {
152 LOG(ERROR) << "Error in decoding the response in generateEcdsaP256KeyPair.";
153 return km_utils::kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR);
154 }
155 *privateKeyHandle = std::move(optPKeyHandle.value());
156 macedPublicKey->macedKey = std::move(optMacedKey.value());
157 return ScopedAStatus::ok();
158 }
159
beginSendData(const std::vector<MacedPublicKey> & keysToSign,const std::vector<uint8_t> & challenge,DeviceInfo * deviceInfo,uint32_t * version,std::string * certificateType)160 ScopedAStatus JavacardRemotelyProvisionedComponentDevice::beginSendData(
161 const std::vector<MacedPublicKey>& keysToSign, const std::vector<uint8_t>& challenge,
162 DeviceInfo* deviceInfo, uint32_t* version, std::string* certificateType) {
163 uint32_t totalEncodedSize = coseKeyEncodedSize(keysToSign);
164 cppbor::Array array;
165 array.add(keysToSign.size());
166 array.add(totalEncodedSize);
167 array.add(challenge);
168 auto [item, err] = card_->sendRequest(Instruction::INS_BEGIN_SEND_DATA_CMD, array);
169 if (err != KM_ERROR_OK) {
170 LOG(ERROR) << "Error in beginSendData.";
171 return km_utils::kmError2ScopedAStatus(translateRkpErrorCode(err));
172 }
173 auto optDecodedDeviceInfo = cbor_.getByteArrayVec(item, 1);
174 if (!optDecodedDeviceInfo) {
175 LOG(ERROR) << "Error in decoding deviceInfo response in beginSendData.";
176 return km_utils::kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR);
177 }
178 deviceInfo->deviceInfo = std::move(optDecodedDeviceInfo.value());
179 auto optVersion = cbor_.getUint64(item, 2);
180 if (!optVersion) {
181 LOG(ERROR) << "Error in decoding version in beginSendData.";
182 return km_utils::kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR);
183 }
184 *version = optVersion.value();
185 auto optCertType = cbor_.getTextStr(item, 3);
186 if (!optCertType) {
187 LOG(ERROR) << "Error in decoding cert type in beginSendData.";
188 return km_utils::kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR);
189 }
190 *certificateType = std::move(optCertType.value());
191 return ScopedAStatus::ok();
192 }
193
updateMacedKey(const std::vector<MacedPublicKey> & keysToSign,Array & coseKeys)194 ScopedAStatus JavacardRemotelyProvisionedComponentDevice::updateMacedKey(
195 const std::vector<MacedPublicKey>& keysToSign, Array& coseKeys) {
196 for (auto& macedPublicKey : keysToSign) {
197 cppbor::Array array;
198 array.add(EncodedItem(macedPublicKey.macedKey));
199 auto [item, err] = card_->sendRequest(Instruction::INS_UPDATE_KEY_CMD, array);
200 if (err != KM_ERROR_OK) {
201 LOG(ERROR) << "Error in updateMacedKey.";
202 return km_utils::kmError2ScopedAStatus(translateRkpErrorCode(err));
203 }
204 auto coseKeyData = cbor_.getByteArrayVec(item, 1);
205 coseKeys.add(EncodedItem(coseKeyData.value()));
206 }
207 return ScopedAStatus::ok();
208 }
209
finishSendData(std::vector<uint8_t> & coseEncryptProtectedHeader,std::vector<uint8_t> & signature,uint32_t & version,uint32_t & respFlag)210 ScopedAStatus JavacardRemotelyProvisionedComponentDevice::finishSendData(
211 std::vector<uint8_t>& coseEncryptProtectedHeader, std::vector<uint8_t>& signature,
212 uint32_t& version, uint32_t& respFlag) {
213 auto [item, err] = card_->sendRequest(Instruction::INS_FINISH_SEND_DATA_CMD);
214 if (err != KM_ERROR_OK) {
215 LOG(ERROR) << "Error in finishSendData.";
216 return km_utils::kmError2ScopedAStatus(translateRkpErrorCode(err));
217 }
218 auto optCEncryptProtectedHeader = cbor_.getByteArrayVec(item, 1);
219 auto optSignature = cbor_.getByteArrayVec(item, 2);
220 auto optVersion = cbor_.getUint64(item, 3);
221 auto optRespFlag = cbor_.getUint64(item, 4);
222 if (!optCEncryptProtectedHeader || !optSignature || !optVersion || !optRespFlag) {
223 LOG(ERROR) << "Error in decoding response in finishSendData.";
224 return km_utils::kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR);
225 }
226
227 coseEncryptProtectedHeader = std::move(optCEncryptProtectedHeader.value());
228 signature.insert(signature.end(), optSignature->begin(), optSignature->end());
229 version = std::move(optVersion.value());
230 respFlag = std::move(optRespFlag.value());
231 return ScopedAStatus::ok();
232 }
233
234 ScopedAStatus
getDiceCertChain(std::vector<uint8_t> & diceCertChain)235 JavacardRemotelyProvisionedComponentDevice::getDiceCertChain(std::vector<uint8_t>& diceCertChain) {
236 uint32_t respFlag = 0;
237 do {
238 auto [item, err] = card_->sendRequest(Instruction::INS_GET_DICE_CERT_CHAIN_CMD);
239 if (err != KM_ERROR_OK) {
240 LOG(ERROR) << "Error in getDiceCertChain.";
241 return km_utils::kmError2ScopedAStatus(translateRkpErrorCode(err));
242 }
243 auto optDiceCertChain = cbor_.getByteArrayVec(item, 1);
244 auto optRespFlag = cbor_.getUint64(item, 2);
245 if (!optDiceCertChain || !optRespFlag) {
246 LOG(ERROR) << "Error in decoding response in getDiceCertChain.";
247 return km_utils::kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR);
248 }
249 respFlag = optRespFlag.value();
250 diceCertChain.insert(diceCertChain.end(), optDiceCertChain->begin(),
251 optDiceCertChain->end());
252 } while (respFlag != 0);
253 return ScopedAStatus::ok();
254 }
255
256 ScopedAStatus
getUdsCertsChain(std::vector<uint8_t> & udsCertsChain)257 JavacardRemotelyProvisionedComponentDevice::getUdsCertsChain(std::vector<uint8_t>& udsCertsChain) {
258 uint32_t respFlag = 0;
259 do {
260 auto [item, err] = card_->sendRequest(Instruction::INS_GET_UDS_CERTS_CMD);
261 if (err != KM_ERROR_OK) {
262 LOG(ERROR) << "Error in getUdsCertsChain.";
263 return km_utils::kmError2ScopedAStatus(translateRkpErrorCode(err));
264 }
265 auto optUdsCertData = cbor_.getByteArrayVec(item, 1);
266 auto optRespFlag = cbor_.getUint64(item, 2);
267 if (!optUdsCertData || !optRespFlag) {
268 LOG(ERROR) << "Error in decoding og response in getUdsCertsChain.";
269 return km_utils::kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR);
270 }
271 respFlag = optRespFlag.value();
272 udsCertsChain.insert(udsCertsChain.end(), optUdsCertData->begin(), optUdsCertData->end());
273 } while (respFlag != 0);
274 return ScopedAStatus::ok();
275 }
276
generateCertificateRequest(bool,const std::vector<MacedPublicKey> &,const std::vector<uint8_t> &,const std::vector<uint8_t> &,DeviceInfo *,ProtectedData *,std::vector<uint8_t> *)277 ScopedAStatus JavacardRemotelyProvisionedComponentDevice::generateCertificateRequest(
278 bool, const std::vector<MacedPublicKey>&, const std::vector<uint8_t>&,
279 const std::vector<uint8_t>&, DeviceInfo*, ProtectedData*, std::vector<uint8_t>*) {
280 return km_utils::kmError2ScopedAStatus(static_cast<keymaster_error_t>(STATUS_REMOVED));
281 }
282
generateCertificateRequestV2(const std::vector<MacedPublicKey> & keysToSign,const std::vector<uint8_t> & challenge,std::vector<uint8_t> * csr)283 ScopedAStatus JavacardRemotelyProvisionedComponentDevice::generateCertificateRequestV2(
284 const std::vector<MacedPublicKey>& keysToSign, const std::vector<uint8_t>& challenge,
285 std::vector<uint8_t>* csr) {
286 uint32_t version;
287 uint32_t csrPayloadSchemaVersion;
288 std::string certificateType;
289 uint32_t respFlag;
290 DeviceInfo deviceInfo;
291 Array coseKeys;
292 std::vector<uint8_t> coseEncryptProtectedHeader;
293 cppbor::Map coseEncryptUnProtectedHeader;
294 std::vector<uint8_t> signature;
295 std::vector<uint8_t> diceCertChain;
296 std::vector<uint8_t> udsCertChain;
297 cppbor::Array payLoad;
298
299 auto ret = beginSendData(keysToSign, challenge, &deviceInfo, &csrPayloadSchemaVersion,
300 &certificateType);
301 if (!ret.isOk()) return ret;
302
303 ret = updateMacedKey(keysToSign, coseKeys);
304 if (!ret.isOk()) return ret;
305
306 ret = finishSendData(coseEncryptProtectedHeader, signature, version, respFlag);
307 if (!ret.isOk()) return ret;
308
309 ret = getUdsCertsChain(udsCertChain);
310 if (!ret.isOk()) return ret;
311
312 ret = getDiceCertChain(diceCertChain);
313 if (!ret.isOk()) return ret;
314
315 auto payload = cppbor::Array()
316 .add(csrPayloadSchemaVersion)
317 .add(certificateType)
318 .add(EncodedItem(deviceInfo.deviceInfo)) // deviceinfo
319 .add(std::move(coseKeys)) // KeysToSign
320 .encode();
321
322 auto signDataPayload = cppbor::Array()
323 .add(challenge) // Challenge
324 .add(std::move(payload))
325 .encode();
326
327 auto signedData = cppbor::Array()
328 .add(std::move(coseEncryptProtectedHeader))
329 .add(cppbor::Map() /* unprotected parameters */)
330 .add(std::move(signDataPayload))
331 .add(std::move(signature));
332
333 *csr = cppbor::Array()
334 .add(version)
335 .add(EncodedItem(std::move(udsCertChain)))
336 .add(EncodedItem(std::move(diceCertChain)))
337 .add(std::move(signedData))
338 .encode();
339
340 return ScopedAStatus::ok();
341 }
342
dump(int,const char **,uint32_t)343 binder_status_t JavacardRemotelyProvisionedComponentDevice::dump(int /* fd */, const char** /* p */,
344 uint32_t /* q */) {
345 LOG(INFO) << "\n KeyMint-JavacardRemotelyProvisionedComponentDevice Info = \n"
346 << ::android::GetUnreachableMemoryString(true, 10000).c_str();
347 return STATUS_OK;
348 }
349
350 } // namespace aidl::android::hardware::security::keymint
351