• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 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     info->rpcAuthorName = std::move(optRpcAuthorName.value());
129     info->versionNumber = static_cast<int32_t>(std::move(optVersionNumber.value()));
130     info->supportedEekCurve = static_cast<int32_t>(std::move(optSupportedEekCurve.value()));
131     info->uniqueId = std::move(optUniqueId.value());
132     info->supportedNumKeysInCsr = static_cast<int32_t>(std::move(optMinSupportedKeysInCsr.value()));
133     return ScopedAStatus::ok();
134 }
135 
generateEcdsaP256KeyPair(bool testMode,MacedPublicKey * macedPublicKey,std::vector<uint8_t> * privateKeyHandle)136 ScopedAStatus JavacardRemotelyProvisionedComponentDevice::generateEcdsaP256KeyPair(
137     bool testMode, MacedPublicKey* macedPublicKey, std::vector<uint8_t>* privateKeyHandle) {
138     if (testMode) {
139         return km_utils::kmError2ScopedAStatus(static_cast<keymaster_error_t>(STATUS_REMOVED));
140     }
141     auto [item, err] = card_->sendRequest(Instruction::INS_GENERATE_RKP_KEY_CMD);
142     if (err != KM_ERROR_OK) {
143         LOG(ERROR) << "Error in sending generateEcdsaP256KeyPair.";
144         return km_utils::kmError2ScopedAStatus(translateRkpErrorCode(err));
145     }
146     std::optional<std::vector<uint8_t>> optMacedKey;
147     std::optional<std::vector<uint8_t>> optPKeyHandle;
148     if (!(optMacedKey = cbor_.getByteArrayVec(item, 1)) ||
149         !(optPKeyHandle = cbor_.getByteArrayVec(item, 2))) {
150         LOG(ERROR) << "Error in decoding the response in generateEcdsaP256KeyPair.";
151         return km_utils::kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR);
152     }
153     *privateKeyHandle = std::move(optPKeyHandle.value());
154     macedPublicKey->macedKey = std::move(optMacedKey.value());
155     return ScopedAStatus::ok();
156 }
157 
beginSendData(const std::vector<MacedPublicKey> & keysToSign,const std::vector<uint8_t> & challenge,DeviceInfo * deviceInfo,uint32_t * version,std::string * certificateType)158 ScopedAStatus JavacardRemotelyProvisionedComponentDevice::beginSendData(
159     const std::vector<MacedPublicKey>& keysToSign, const std::vector<uint8_t>& challenge,
160     DeviceInfo* deviceInfo, uint32_t* version, std::string* certificateType) {
161     uint32_t totalEncodedSize = coseKeyEncodedSize(keysToSign);
162     cppbor::Array array;
163     array.add(keysToSign.size());
164     array.add(totalEncodedSize);
165     array.add(challenge);
166     auto [item, err] = card_->sendRequest(Instruction::INS_BEGIN_SEND_DATA_CMD, array);
167     if (err != KM_ERROR_OK) {
168         LOG(ERROR) << "Error in beginSendData.";
169         return km_utils::kmError2ScopedAStatus(translateRkpErrorCode(err));
170     }
171     auto optDecodedDeviceInfo = cbor_.getByteArrayVec(item, 1);
172     if (!optDecodedDeviceInfo) {
173         LOG(ERROR) << "Error in decoding deviceInfo response in beginSendData.";
174         return km_utils::kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR);
175     }
176     deviceInfo->deviceInfo = std::move(optDecodedDeviceInfo.value());
177     auto optVersion = cbor_.getUint64(item, 2);
178     if (!optVersion) {
179         LOG(ERROR) << "Error in decoding version in beginSendData.";
180         return km_utils::kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR);
181     }
182     *version = optVersion.value();
183     auto optCertType = cbor_.getTextStr(item, 3);
184     if (!optCertType) {
185         LOG(ERROR) << "Error in decoding cert type in beginSendData.";
186         return km_utils::kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR);
187     }
188     *certificateType = std::move(optCertType.value());
189     return ScopedAStatus::ok();
190 }
191 
updateMacedKey(const std::vector<MacedPublicKey> & keysToSign,Array & coseKeys)192 ScopedAStatus JavacardRemotelyProvisionedComponentDevice::updateMacedKey(
193     const std::vector<MacedPublicKey>& keysToSign, Array& coseKeys) {
194     for (auto& macedPublicKey : keysToSign) {
195         cppbor::Array array;
196         array.add(EncodedItem(macedPublicKey.macedKey));
197         auto [item, err] = card_->sendRequest(Instruction::INS_UPDATE_KEY_CMD, array);
198         if (err != KM_ERROR_OK) {
199             LOG(ERROR) << "Error in updateMacedKey.";
200             return km_utils::kmError2ScopedAStatus(translateRkpErrorCode(err));
201         }
202         auto coseKeyData = cbor_.getByteArrayVec(item, 1);
203         coseKeys.add(EncodedItem(coseKeyData.value()));
204     }
205     return ScopedAStatus::ok();
206 }
207 
finishSendData(std::vector<uint8_t> & coseEncryptProtectedHeader,std::vector<uint8_t> & signature,uint32_t & version,uint32_t & respFlag)208 ScopedAStatus JavacardRemotelyProvisionedComponentDevice::finishSendData(
209     std::vector<uint8_t>& coseEncryptProtectedHeader, std::vector<uint8_t>& signature,
210     uint32_t& version, uint32_t& respFlag) {
211     auto [item, err] = card_->sendRequest(Instruction::INS_FINISH_SEND_DATA_CMD);
212     if (err != KM_ERROR_OK) {
213         LOG(ERROR) << "Error in finishSendData.";
214         return km_utils::kmError2ScopedAStatus(translateRkpErrorCode(err));
215     }
216     auto optCEncryptProtectedHeader = cbor_.getByteArrayVec(item, 1);
217     auto optSignature = cbor_.getByteArrayVec(item, 2);
218     auto optVersion = cbor_.getUint64(item, 3);
219     auto optRespFlag = cbor_.getUint64(item, 4);
220     if (!optCEncryptProtectedHeader || !optSignature || !optVersion || !optRespFlag) {
221         LOG(ERROR) << "Error in decoding response in finishSendData.";
222         return km_utils::kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR);
223     }
224 
225     coseEncryptProtectedHeader = std::move(optCEncryptProtectedHeader.value());
226     signature.insert(signature.end(), optSignature->begin(), optSignature->end());
227     version = std::move(optVersion.value());
228     respFlag = std::move(optRespFlag.value());
229     return ScopedAStatus::ok();
230 }
231 
232 ScopedAStatus
getDiceCertChain(std::vector<uint8_t> & diceCertChain)233 JavacardRemotelyProvisionedComponentDevice::getDiceCertChain(std::vector<uint8_t>& diceCertChain) {
234     uint32_t respFlag = 0;
235     do {
236         auto [item, err] = card_->sendRequest(Instruction::INS_GET_DICE_CERT_CHAIN_CMD);
237         if (err != KM_ERROR_OK) {
238             LOG(ERROR) << "Error in getDiceCertChain.";
239             return km_utils::kmError2ScopedAStatus(translateRkpErrorCode(err));
240         }
241         auto optDiceCertChain = cbor_.getByteArrayVec(item, 1);
242         auto optRespFlag = cbor_.getUint64(item, 2);
243         if (!optDiceCertChain || !optRespFlag) {
244             LOG(ERROR) << "Error in decoding response in getDiceCertChain.";
245             return km_utils::kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR);
246         }
247         respFlag = optRespFlag.value();
248         diceCertChain.insert(diceCertChain.end(), optDiceCertChain->begin(),
249                              optDiceCertChain->end());
250     } while (respFlag != 0);
251     return ScopedAStatus::ok();
252 }
253 
254 ScopedAStatus
getUdsCertsChain(std::vector<uint8_t> & udsCertsChain)255 JavacardRemotelyProvisionedComponentDevice::getUdsCertsChain(std::vector<uint8_t>& udsCertsChain) {
256     uint32_t respFlag = 0;
257     do {
258         auto [item, err] = card_->sendRequest(Instruction::INS_GET_UDS_CERTS_CMD);
259         if (err != KM_ERROR_OK) {
260             LOG(ERROR) << "Error in getUdsCertsChain.";
261             return km_utils::kmError2ScopedAStatus(translateRkpErrorCode(err));
262         }
263         auto optUdsCertData = cbor_.getByteArrayVec(item, 1);
264         auto optRespFlag = cbor_.getUint64(item, 2);
265         if (!optUdsCertData || !optRespFlag) {
266             LOG(ERROR) << "Error in decoding og response in getUdsCertsChain.";
267             return km_utils::kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR);
268         }
269         respFlag = optRespFlag.value();
270         udsCertsChain.insert(udsCertsChain.end(), optUdsCertData->begin(), optUdsCertData->end());
271     } while (respFlag != 0);
272     return ScopedAStatus::ok();
273 }
274 
generateCertificateRequest(bool,const std::vector<MacedPublicKey> &,const std::vector<uint8_t> &,const std::vector<uint8_t> &,DeviceInfo *,ProtectedData *,std::vector<uint8_t> *)275 ScopedAStatus JavacardRemotelyProvisionedComponentDevice::generateCertificateRequest(
276     bool, const std::vector<MacedPublicKey>&, const std::vector<uint8_t>&,
277     const std::vector<uint8_t>&, DeviceInfo*, ProtectedData*, std::vector<uint8_t>*) {
278     return km_utils::kmError2ScopedAStatus(static_cast<keymaster_error_t>(STATUS_REMOVED));
279 }
280 
generateCertificateRequestV2(const std::vector<MacedPublicKey> & keysToSign,const std::vector<uint8_t> & challenge,std::vector<uint8_t> * csr)281 ScopedAStatus JavacardRemotelyProvisionedComponentDevice::generateCertificateRequestV2(
282     const std::vector<MacedPublicKey>& keysToSign, const std::vector<uint8_t>& challenge,
283     std::vector<uint8_t>* csr) {
284     uint32_t version;
285     uint32_t csrPayloadSchemaVersion;
286     std::string certificateType;
287     uint32_t respFlag;
288     DeviceInfo deviceInfo;
289     Array coseKeys;
290     std::vector<uint8_t> coseEncryptProtectedHeader;
291     cppbor::Map coseEncryptUnProtectedHeader;
292     std::vector<uint8_t> signature;
293     std::vector<uint8_t> diceCertChain;
294     std::vector<uint8_t> udsCertChain;
295     cppbor::Array payLoad;
296 
297     auto ret = beginSendData(keysToSign, challenge, &deviceInfo, &csrPayloadSchemaVersion,
298                              &certificateType);
299     if (!ret.isOk()) return ret;
300 
301     ret = updateMacedKey(keysToSign, coseKeys);
302     if (!ret.isOk()) return ret;
303 
304     ret = finishSendData(coseEncryptProtectedHeader, signature, version, respFlag);
305     if (!ret.isOk()) return ret;
306 
307     ret = getUdsCertsChain(udsCertChain);
308     if (!ret.isOk()) return ret;
309 
310     ret = getDiceCertChain(diceCertChain);
311     if (!ret.isOk()) return ret;
312 
313     auto payload = cppbor::Array()
314                        .add(csrPayloadSchemaVersion)
315                        .add(certificateType)
316                        .add(EncodedItem(deviceInfo.deviceInfo))  // deviceinfo
317                        .add(std::move(coseKeys))                 // KeysToSign
318                        .encode();
319 
320     auto signDataPayload = cppbor::Array()
321                                .add(challenge)  // Challenge
322                                .add(std::move(payload))
323                                .encode();
324 
325     auto signedData = cppbor::Array()
326                           .add(std::move(coseEncryptProtectedHeader))
327                           .add(cppbor::Map() /* unprotected parameters */)
328                           .add(std::move(signDataPayload))
329                           .add(std::move(signature));
330 
331     *csr = cppbor::Array()
332                .add(version)
333                .add(EncodedItem(std::move(udsCertChain)))
334                .add(EncodedItem(std::move(diceCertChain)))
335                .add(std::move(signedData))
336                .encode();
337 
338     return ScopedAStatus::ok();
339 }
340 
dump(int,const char **,uint32_t)341 binder_status_t JavacardRemotelyProvisionedComponentDevice::dump(int /* fd */, const char** /* p */,
342                                                                  uint32_t /* q */) {
343     LOG(INFO) << "\n KeyMint-JavacardRemotelyProvisionedComponentDevice Info = \n"
344               << ::android::GetUnreachableMemoryString(true, 10000).c_str();
345     return STATUS_OK;
346 }
347 
348 }  // namespace aidl::android::hardware::security::keymint
349