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