• 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 2022-2024 NXP
33  **
34  *********************************************************************************/
35 
36 #define LOG_TAG "javacard.keymint.device.rkp.strongbox-impl"
37 #include <JavacardKeyMintUtils.h>
38 #include <JavacardRemotelyProvisionedComponentDevice.h>
39 #include <aidl/android/hardware/security/keymint/MacedPublicKey.h>
40 #include <android-base/logging.h>
41 #include <keymaster/cppcose/cppcose.h>
42 #include <keymaster/remote_provisioning_utils.h>
43 #include <memunreachable/memunreachable.h>
44 
45 #ifdef NXP_EXTNS
46 #define KM_RKP_VERSION_1 0x01
47 #endif
48 
49 namespace aidl::android::hardware::security::keymint {
50 using cppbor::Array;
51 using cppbor::EncodedItem;
52 using cppcose::kCoseMac0EntryCount;
53 using cppcose::kCoseMac0Payload;
54 using ::keymint::javacard::Instruction;
55 // RKP error codes defined in keymint applet.
56 constexpr int32_t kStatusFailed = 32000;
57 constexpr int32_t kStatusInvalidMac = 32001;
58 constexpr int32_t kStatusProductionKeyInTestRequest = 32002;
59 constexpr int32_t kStatusTestKeyInProductionRequest = 32003;
60 constexpr int32_t kStatusInvalidEek = 32004;
61 constexpr int32_t kStatusInvalidState = 32005;
62 
63 namespace {
64 
translateRkpErrorCode(keymaster_error_t error)65 keymaster_error_t translateRkpErrorCode(keymaster_error_t error) {
66     switch(static_cast<int32_t>(-error)) {
67         case kStatusFailed:
68         case kStatusInvalidState:
69             return static_cast<keymaster_error_t>(BnRemotelyProvisionedComponent::STATUS_FAILED);
70         case kStatusInvalidMac:
71             return static_cast<keymaster_error_t>(BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
72         case kStatusProductionKeyInTestRequest:
73             return static_cast<keymaster_error_t>(BnRemotelyProvisionedComponent::STATUS_PRODUCTION_KEY_IN_TEST_REQUEST);
74         case kStatusTestKeyInProductionRequest:
75             return static_cast<keymaster_error_t>(BnRemotelyProvisionedComponent::STATUS_TEST_KEY_IN_PRODUCTION_REQUEST);
76         case kStatusInvalidEek:
77             return static_cast<keymaster_error_t>(BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
78     }
79     return error;
80 }
81 
defaultHwInfo(RpcHardwareInfo * info)82 ScopedAStatus defaultHwInfo(RpcHardwareInfo* info) {
83     info->versionNumber = 1;
84     info->rpcAuthorName = "Google";
85     info->supportedEekCurve = RpcHardwareInfo::CURVE_P256;
86     return ScopedAStatus::ok();
87 }
88 
coseKeyEncodedSize(const std::vector<MacedPublicKey> & keysToSign)89 uint32_t coseKeyEncodedSize(const std::vector<MacedPublicKey>& keysToSign) {
90     uint32_t size = 0;
91     for(auto& macKey : keysToSign) {
92         auto [macedKeyItem, _, coseMacErrMsg] =
93             cppbor::parse(macKey.macedKey);
94         if (!macedKeyItem || !macedKeyItem->asArray() ||
95             macedKeyItem->asArray()->size() != kCoseMac0EntryCount) {
96             LOG(ERROR) << "Invalid COSE_Mac0 structure";
97             return 0;
98         }
99         auto payload = macedKeyItem->asArray()->get(kCoseMac0Payload)->asBstr();
100         if (!payload) return 0;
101         size += payload->value().size();
102     }
103     return size;
104 }
105 
106 } // namespace
107 
108 ScopedAStatus
getHardwareInfo(RpcHardwareInfo * info)109 JavacardRemotelyProvisionedComponentDevice::getHardwareInfo(RpcHardwareInfo* info) {
110     auto [item, err] = card_->sendRequest(Instruction::INS_GET_RKP_HARDWARE_INFO);
111     uint32_t versionNumber;
112     uint32_t supportedEekCurve;
113     if (err != KM_ERROR_OK ||
114         !cbor_.getUint64<uint32_t>(item, 1, versionNumber) ||
115         !cbor_.getBinaryArray(item, 2, info->rpcAuthorName ) ||
116         !cbor_.getUint64<uint32_t>(item, 3, supportedEekCurve)) {
117         LOG(ERROR) << "Error in response of getHardwareInfo.";
118         LOG(INFO) << "Returning defaultHwInfo in getHardwareInfo.";
119         return defaultHwInfo(info);
120     }
121     info->versionNumber = static_cast<int32_t>(versionNumber);
122 #ifdef NXP_EXTNS
123     if (info->versionNumber > KM_RKP_VERSION_1) {
124         std::string uniqueId;
125         if (!cbor_.getBinaryArray(item, 4, uniqueId)) {
126             LOG(ERROR) << "Error in uniqueId response of getHardwareInfo.";
127             LOG(INFO) << "Returning defaultHwInfo in getHardwareInfo.";
128             return defaultHwInfo(info);
129         }
130         info->uniqueId = static_cast<::std::optional<::std::string>>(uniqueId);
131     }
132 #endif
133     info->supportedEekCurve = static_cast<int32_t>(supportedEekCurve);
134     return ScopedAStatus::ok();
135 }
136 
137 ScopedAStatus
generateEcdsaP256KeyPair(bool testMode,MacedPublicKey * macedPublicKey,std::vector<uint8_t> * privateKeyHandle)138 JavacardRemotelyProvisionedComponentDevice::generateEcdsaP256KeyPair(bool testMode,
139                                                 MacedPublicKey* macedPublicKey,
140                                                 std::vector<uint8_t>* privateKeyHandle) {
141     cppbor::Array array;
142     array.add(testMode);
143     auto [item, err] = card_->sendRequest(Instruction::INS_GENERATE_RKP_KEY_CMD, array);
144     if (err != KM_ERROR_OK) {
145         LOG(ERROR) << "Error in sending generateEcdsaP256KeyPair.";
146         return km_utils::kmError2ScopedAStatus(translateRkpErrorCode(err));
147     }
148     if (!cbor_.getBinaryArray(item, 1, macedPublicKey->macedKey) ||
149         !cbor_.getBinaryArray(item, 2, *privateKeyHandle)) {
150          LOG(ERROR) << "Error in decoding og response in generateEcdsaP256KeyPair.";
151          return km_utils::kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR);
152     }
153     return ScopedAStatus::ok();
154 }
155 
156 ScopedAStatus
beginSendData(bool testMode,const std::vector<MacedPublicKey> & keysToSign)157 JavacardRemotelyProvisionedComponentDevice::beginSendData(
158     bool testMode, const std::vector<MacedPublicKey>& keysToSign) {
159     uint32_t totalEncodedSize = coseKeyEncodedSize(keysToSign);
160     cppbor::Array array;
161     array.add(keysToSign.size());
162     array.add(totalEncodedSize);
163     array.add(testMode);
164     auto [_, err] = card_->sendRequest(Instruction::INS_BEGIN_SEND_DATA_CMD, array);
165     if (err != KM_ERROR_OK) {
166         LOG(ERROR) << "Error in beginSendData.";
167         return km_utils::kmError2ScopedAStatus(translateRkpErrorCode(err));
168     }
169     return ScopedAStatus::ok();
170 }
171 
172 ScopedAStatus
updateMacedKey(const std::vector<MacedPublicKey> & keysToSign)173 JavacardRemotelyProvisionedComponentDevice::updateMacedKey(
174     const std::vector<MacedPublicKey>& keysToSign) {
175     for(auto& macedPublicKey : keysToSign) {
176         cppbor::Array array;
177         array.add(EncodedItem(macedPublicKey.macedKey));
178         auto [_, err] = card_->sendRequest(Instruction::INS_UPDATE_KEY_CMD, array);
179         if (err != KM_ERROR_OK) {
180             LOG(ERROR) << "Error in updateMacedKey.";
181             return km_utils::kmError2ScopedAStatus(translateRkpErrorCode(err));
182         }
183     }
184     return ScopedAStatus::ok();
185 }
186 
187 ScopedAStatus
updateChallenge(const std::vector<uint8_t> & challenge)188 JavacardRemotelyProvisionedComponentDevice::updateChallenge(
189     const std::vector<uint8_t>& challenge) {
190     Array array;
191     array.add(challenge);
192     auto [_, err] = card_->sendRequest(Instruction::INS_UPDATE_CHALLENGE_CMD, array);
193     if (err != KM_ERROR_OK) {
194         LOG(ERROR) << "Error in updateChallenge.";
195         return km_utils::kmError2ScopedAStatus(translateRkpErrorCode(err));
196     }
197     return ScopedAStatus::ok();
198 }
199 
200 ScopedAStatus
updateEEK(const std::vector<uint8_t> & endpointEncCertChain)201 JavacardRemotelyProvisionedComponentDevice::updateEEK(
202     const std::vector<uint8_t>& endpointEncCertChain) {
203     std::vector<uint8_t> eekChain = endpointEncCertChain;
204     auto [_, err] = card_->sendRequest(Instruction::INS_UPDATE_EEK_CHAIN_CMD, eekChain);
205     if (err != KM_ERROR_OK) {
206         LOG(ERROR) << "Error in updateEEK.";
207         return km_utils::kmError2ScopedAStatus(translateRkpErrorCode(err));
208     }
209     return ScopedAStatus::ok();
210 }
211 
212 ScopedAStatus
finishSendData(std::vector<uint8_t> * keysToSignMac,DeviceInfo * deviceInfo,std::vector<uint8_t> & coseEncryptProtectedHeader,cppbor::Map & coseEncryptUnProtectedHeader,std::vector<uint8_t> & partialCipheredData,uint32_t & respFlag)213 JavacardRemotelyProvisionedComponentDevice::finishSendData(
214     std::vector<uint8_t>* keysToSignMac, DeviceInfo* deviceInfo,
215     std::vector<uint8_t>& coseEncryptProtectedHeader, cppbor::Map& coseEncryptUnProtectedHeader,
216     std::vector<uint8_t>& partialCipheredData, uint32_t& respFlag) {
217 
218     std::vector<uint8_t> decodedKeysToSignMac;
219     std::vector<uint8_t> decodedDeviceInfo;
220     auto [item, err] = card_->sendRequest(Instruction::INS_FINISH_SEND_DATA_CMD);
221     if (err != KM_ERROR_OK) {
222         LOG(ERROR) << "Error in finishSendData.";
223         return km_utils::kmError2ScopedAStatus(translateRkpErrorCode(err));
224     }
225     if (!cbor_.getBinaryArray(item, 1, decodedKeysToSignMac) ||
226         !cbor_.getBinaryArray(item, 2, decodedDeviceInfo) ||
227         !cbor_.getBinaryArray(item, 3, coseEncryptProtectedHeader) ||
228         !cbor_.getMapItem(item, 4, coseEncryptUnProtectedHeader) ||
229         !cbor_.getBinaryArray(item, 5, partialCipheredData) ||
230         !cbor_.getUint64(item, 6, respFlag)) {
231          LOG(ERROR) << "Error in decoding og response in finishSendData.";
232          return km_utils::kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR);
233     }
234     *keysToSignMac = decodedKeysToSignMac;
235     deviceInfo->deviceInfo = decodedDeviceInfo;
236     return ScopedAStatus::ok();
237 }
238 
239 ScopedAStatus
getResponse(std::vector<uint8_t> & partialCipheredData,cppbor::Array & recipientStructure,uint32_t & respFlag)240 JavacardRemotelyProvisionedComponentDevice::getResponse(
241     std::vector<uint8_t>& partialCipheredData, cppbor::Array& recipientStructure,
242     uint32_t& respFlag) {
243     auto [item, err] = card_->sendRequest(Instruction::INS_GET_RESPONSE_CMD);
244     if (err != KM_ERROR_OK) {
245         LOG(ERROR) << "Error in getResponse.";
246         return km_utils::kmError2ScopedAStatus(translateRkpErrorCode(err));
247     }
248     if (!cbor_.getBinaryArray(item, 1, partialCipheredData) ||
249         !cbor_.getArrayItem(item, 2, recipientStructure) ||
250         !cbor_.getUint64(item, 3, respFlag)) {
251          LOG(ERROR) << "Error in decoding og response in getResponse.";
252          return km_utils::kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR);
253     }
254     return ScopedAStatus::ok();
255 }
256 
257 ScopedAStatus
generateCertificateRequest(bool testMode,const std::vector<MacedPublicKey> & keysToSign,const std::vector<uint8_t> & endpointEncCertChain,const std::vector<uint8_t> & challenge,DeviceInfo * deviceInfo,ProtectedData * protectedData,std::vector<uint8_t> * keysToSignMac)258 JavacardRemotelyProvisionedComponentDevice::generateCertificateRequest(bool testMode,
259                                         const std::vector<MacedPublicKey>& keysToSign,
260                                         const std::vector<uint8_t>& endpointEncCertChain,
261                                         const std::vector<uint8_t>& challenge,
262                                         DeviceInfo* deviceInfo, ProtectedData* protectedData,
263                                         std::vector<uint8_t>* keysToSignMac) {
264     std::vector<uint8_t> coseEncryptProtectedHeader;
265     cppbor::Map coseEncryptUnProtectedHeader;
266     cppbor::Array recipients;
267     std::vector<uint8_t> cipheredData;
268     uint32_t respFlag;
269     auto ret = beginSendData(testMode, keysToSign);
270     if (!ret.isOk()) return ret;
271 
272     ret = updateMacedKey(keysToSign);
273     if (!ret.isOk()) return ret;
274 
275     ret = updateChallenge(challenge);
276     if (!ret.isOk()) return ret;
277 
278     ret = updateEEK(endpointEncCertChain);
279     if (!ret.isOk()) return ret;
280 
281     ret = finishSendData(keysToSignMac, deviceInfo, coseEncryptProtectedHeader,
282                          coseEncryptUnProtectedHeader, cipheredData,
283                          respFlag);
284     if (!ret.isOk()) return ret;
285 
286     while (respFlag != 0) { // more data is pending to receive
287         ret = getResponse(cipheredData, recipients, respFlag);
288         if (!ret.isOk()) return ret;
289     }
290     // Create ConseEncrypt structure.
291     protectedData->protectedData =
292         cppbor::Array()
293             .add(coseEncryptProtectedHeader)    // Protected
294             .add(std::move(coseEncryptUnProtectedHeader))  // Unprotected
295             .add(cipheredData)           // Payload
296             .add(std::move(recipients))
297             .encode();
298     return ScopedAStatus::ok();
299 }
300 
dump(int,const char **,uint32_t)301 binder_status_t JavacardRemotelyProvisionedComponentDevice::dump(int /* fd */, const char** /* p */,
302                                                                  uint32_t /* q */) {
303     LOG(INFO) << "\n KeyMint-JavacardRemotelyProvisionedComponentDevice Info = \n"
304               << ::android::GetUnreachableMemoryString(true, 10000).c_str();
305     return STATUS_OK;
306 }
307 
308 } // namespace aidl::android::hardware::security::keymint
309