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