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