• 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 #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(keymaster_error_t error)46 keymaster_error_t translateRkpErrorCode(keymaster_error_t error) {
47     switch (static_cast<int32_t>(-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 error;
63 }
64 
defaultHwInfo(RpcHardwareInfo * info)65 ScopedAStatus defaultHwInfo(RpcHardwareInfo* info) {
66     info->versionNumber = 3;
67     info->rpcAuthorName = "Google";
68     info->supportedEekCurve = RpcHardwareInfo::CURVE_NONE;
69     info->uniqueId = "Google Strongbox KeyMint 3";
70     info->supportedNumKeysInCsr = RpcHardwareInfo::MIN_SUPPORTED_NUM_KEYS_IN_CSR;
71     return ScopedAStatus::ok();
72 }
73 
coseKeyEncodedSize(const std::vector<MacedPublicKey> & keysToSign)74 uint32_t coseKeyEncodedSize(const std::vector<MacedPublicKey>& keysToSign) {
75     uint32_t size = 0;
76     for (auto& macKey : keysToSign) {
77         auto [macedKeyItem, _, coseMacErrMsg] = cppbor::parse(macKey.macedKey);
78         if (!macedKeyItem || !macedKeyItem->asArray() ||
79             macedKeyItem->asArray()->size() != kCoseMac0EntryCount) {
80             LOG(ERROR) << "Invalid COSE_Mac0 structure";
81             return 0;
82         }
83         auto payload = macedKeyItem->asArray()->get(kCoseMac0Payload)->asBstr();
84         if (!payload) return 0;
85         size += payload->value().size();
86     }
87     return size;
88 }
89 
90 }  // namespace
91 
getHardwareInfo(RpcHardwareInfo * info)92 ScopedAStatus JavacardRemotelyProvisionedComponentDevice::getHardwareInfo(RpcHardwareInfo* info) {
93     auto [item, err] = card_->sendRequest(Instruction::INS_GET_RKP_HARDWARE_INFO);
94     std::optional<uint64_t> optVersionNumber;
95     std::optional<uint64_t> optSupportedEekCurve;
96     std::optional<string> optRpcAuthorName;
97     std::optional<string> optUniqueId;
98     std::optional<uint64_t> optMinSupportedKeysInCsr;
99     if (err != KM_ERROR_OK || !(optVersionNumber = cbor_.getUint64(item, 1)) ||
100         !(optRpcAuthorName = cbor_.getByteArrayStr(item, 2)) ||
101         !(optSupportedEekCurve = cbor_.getUint64(item, 3)) ||
102         !(optUniqueId = cbor_.getByteArrayStr(item, 4)) ||
103         !(optMinSupportedKeysInCsr = cbor_.getUint64(item, 5))) {
104         LOG(ERROR) << "Error in response of getHardwareInfo.";
105         LOG(INFO) << "Returning defaultHwInfo in getHardwareInfo.";
106         return defaultHwInfo(info);
107     }
108     info->rpcAuthorName = std::move(optRpcAuthorName.value());
109     info->versionNumber = static_cast<int32_t>(std::move(optVersionNumber.value()));
110     info->supportedEekCurve = static_cast<int32_t>(std::move(optSupportedEekCurve.value()));
111     info->uniqueId = std::move(optUniqueId.value());
112     info->supportedNumKeysInCsr = static_cast<int32_t>(std::move(optMinSupportedKeysInCsr.value()));
113     return ScopedAStatus::ok();
114 }
115 
generateEcdsaP256KeyPair(bool testMode,MacedPublicKey * macedPublicKey,std::vector<uint8_t> * privateKeyHandle)116 ScopedAStatus JavacardRemotelyProvisionedComponentDevice::generateEcdsaP256KeyPair(
117     bool testMode, MacedPublicKey* macedPublicKey, std::vector<uint8_t>* privateKeyHandle) {
118     cppbor::Array array;
119     array.add(testMode);
120     auto [item, err] = card_->sendRequest(Instruction::INS_GENERATE_RKP_KEY_CMD, array);
121     if (err != KM_ERROR_OK) {
122         LOG(ERROR) << "Error in sending generateEcdsaP256KeyPair.";
123         return km_utils::kmError2ScopedAStatus(translateRkpErrorCode(err));
124     }
125     std::optional<std::vector<uint8_t>> optMacedKey;
126     std::optional<std::vector<uint8_t>> optPKeyHandle;
127     if (!(optMacedKey = cbor_.getByteArrayVec(item, 1)) ||
128         !(optPKeyHandle = cbor_.getByteArrayVec(item, 2))) {
129         LOG(ERROR) << "Error in decoding the response in generateEcdsaP256KeyPair.";
130         return km_utils::kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR);
131     }
132     *privateKeyHandle = std::move(optPKeyHandle.value());
133     macedPublicKey->macedKey = std::move(optMacedKey.value());
134     return ScopedAStatus::ok();
135 }
136 
beginSendData(const std::vector<MacedPublicKey> & keysToSign,const std::vector<uint8_t> & challenge,DeviceInfo * deviceInfo,uint32_t * version,std::string * certificateType)137 ScopedAStatus JavacardRemotelyProvisionedComponentDevice::beginSendData(
138     const std::vector<MacedPublicKey>& keysToSign, const std::vector<uint8_t>& challenge,
139     DeviceInfo* deviceInfo, uint32_t* version, std::string* certificateType) {
140     uint32_t totalEncodedSize = coseKeyEncodedSize(keysToSign);
141     cppbor::Array array;
142     array.add(keysToSign.size());
143     array.add(totalEncodedSize);
144     array.add(challenge);
145     auto [item, err] = card_->sendRequest(Instruction::INS_BEGIN_SEND_DATA_CMD, array);
146     if (err != KM_ERROR_OK) {
147         LOG(ERROR) << "Error in beginSendData.";
148         return km_utils::kmError2ScopedAStatus(translateRkpErrorCode(err));
149     }
150     auto optDecodedDeviceInfo = cbor_.getByteArrayVec(item, 1);
151     if (!optDecodedDeviceInfo) {
152         LOG(ERROR) << "Error in decoding deviceInfo response in beginSendData.";
153         return km_utils::kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR);
154     }
155     deviceInfo->deviceInfo = std::move(optDecodedDeviceInfo.value());
156     auto optVersion = cbor_.getUint64(item, 2);
157     if (!optVersion) {
158         LOG(ERROR) << "Error in decoding version in beginSendData.";
159         return km_utils::kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR);
160     }
161     *version = optVersion.value();
162     auto optCertType = cbor_.getTextStr(item, 3);
163     if (!optCertType) {
164         LOG(ERROR) << "Error in decoding cert type in beginSendData.";
165         return km_utils::kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR);
166     }
167     *certificateType = std::move(optCertType.value());
168     return ScopedAStatus::ok();
169 }
170 
updateMacedKey(const std::vector<MacedPublicKey> & keysToSign,Array & coseKeys)171 ScopedAStatus JavacardRemotelyProvisionedComponentDevice::updateMacedKey(
172     const std::vector<MacedPublicKey>& keysToSign, Array& coseKeys) {
173     for (auto& macedPublicKey : keysToSign) {
174         cppbor::Array array;
175         array.add(EncodedItem(macedPublicKey.macedKey));
176         auto [item, err] = card_->sendRequest(Instruction::INS_UPDATE_KEY_CMD, array);
177         if (err != KM_ERROR_OK) {
178             LOG(ERROR) << "Error in updateMacedKey.";
179             return km_utils::kmError2ScopedAStatus(translateRkpErrorCode(err));
180         }
181         auto coseKeyData = cbor_.getByteArrayVec(item, 1);
182         coseKeys.add(EncodedItem(coseKeyData.value()));
183     }
184     return ScopedAStatus::ok();
185 }
186 
finishSendData(std::vector<uint8_t> & coseEncryptProtectedHeader,std::vector<uint8_t> & signature,uint32_t & version,uint32_t & respFlag)187 ScopedAStatus JavacardRemotelyProvisionedComponentDevice::finishSendData(
188     std::vector<uint8_t>& coseEncryptProtectedHeader, std::vector<uint8_t>& signature,
189     uint32_t& version, uint32_t& respFlag) {
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 optCEncryptProtectedHeader = cbor_.getByteArrayVec(item, 1);
196     auto optSignature = cbor_.getByteArrayVec(item, 2);
197     auto optVersion = cbor_.getUint64(item, 3);
198     auto optRespFlag = cbor_.getUint64(item, 4);
199     if (!optCEncryptProtectedHeader || !optSignature || !optVersion || !optRespFlag) {
200         LOG(ERROR) << "Error in decoding response in finishSendData.";
201         return km_utils::kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR);
202     }
203 
204     coseEncryptProtectedHeader = std::move(optCEncryptProtectedHeader.value());
205     signature.insert(signature.end(), optSignature->begin(), optSignature->end());
206     version = std::move(optVersion.value());
207     respFlag = std::move(optRespFlag.value());
208     return ScopedAStatus::ok();
209 }
210 
211 ScopedAStatus
getDiceCertChain(std::vector<uint8_t> & diceCertChain)212 JavacardRemotelyProvisionedComponentDevice::getDiceCertChain(std::vector<uint8_t>& diceCertChain) {
213     uint32_t respFlag = 0;
214     do {
215         auto [item, err] = card_->sendRequest(Instruction::INS_GET_DICE_CERT_CHAIN_CMD);
216         if (err != KM_ERROR_OK) {
217             LOG(ERROR) << "Error in getDiceCertChain.";
218             return km_utils::kmError2ScopedAStatus(translateRkpErrorCode(err));
219         }
220         auto optDiceCertChain = cbor_.getByteArrayVec(item, 1);
221         auto optRespFlag = cbor_.getUint64(item, 2);
222         if (!optDiceCertChain || !optRespFlag) {
223             LOG(ERROR) << "Error in decoding response in getDiceCertChain.";
224             return km_utils::kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR);
225         }
226         respFlag = optRespFlag.value();
227         diceCertChain.insert(diceCertChain.end(), optDiceCertChain->begin(),
228                              optDiceCertChain->end());
229     } while (respFlag != 0);
230     return ScopedAStatus::ok();
231 }
232 
233 ScopedAStatus
getUdsCertsChain(std::vector<uint8_t> & udsCertsChain)234 JavacardRemotelyProvisionedComponentDevice::getUdsCertsChain(std::vector<uint8_t>& udsCertsChain) {
235     uint32_t respFlag = 0;
236     do {
237         auto [item, err] = card_->sendRequest(Instruction::INS_GET_UDS_CERTS_CMD);
238         if (err != KM_ERROR_OK) {
239             LOG(ERROR) << "Error in getUdsCertsChain.";
240             return km_utils::kmError2ScopedAStatus(translateRkpErrorCode(err));
241         }
242         auto optUdsCertData = cbor_.getByteArrayVec(item, 1);
243         auto optRespFlag = cbor_.getUint64(item, 2);
244         if (!optUdsCertData || !optRespFlag) {
245             LOG(ERROR) << "Error in decoding og response in getUdsCertsChain.";
246             return km_utils::kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR);
247         }
248         respFlag = optRespFlag.value();
249         udsCertsChain.insert(udsCertsChain.end(), optUdsCertData->begin(), optUdsCertData->end());
250     } while (respFlag != 0);
251     return ScopedAStatus::ok();
252 }
253 
generateCertificateRequest(bool,const std::vector<MacedPublicKey> &,const std::vector<uint8_t> &,const std::vector<uint8_t> &,DeviceInfo *,ProtectedData *,std::vector<uint8_t> *)254 ScopedAStatus JavacardRemotelyProvisionedComponentDevice::generateCertificateRequest(
255     bool, const std::vector<MacedPublicKey>&, const std::vector<uint8_t>&,
256     const std::vector<uint8_t>&, DeviceInfo*, ProtectedData*, std::vector<uint8_t>*) {
257     return km_utils::kmError2ScopedAStatus(static_cast<keymaster_error_t>(STATUS_REMOVED));
258 }
259 
generateCertificateRequestV2(const std::vector<MacedPublicKey> & keysToSign,const std::vector<uint8_t> & challenge,std::vector<uint8_t> * csr)260 ScopedAStatus JavacardRemotelyProvisionedComponentDevice::generateCertificateRequestV2(
261     const std::vector<MacedPublicKey>& keysToSign, const std::vector<uint8_t>& challenge,
262     std::vector<uint8_t>* csr) {
263     uint32_t version;
264     uint32_t csrPayloadSchemaVersion;
265     std::string certificateType;
266     uint32_t respFlag;
267     DeviceInfo deviceInfo;
268     Array coseKeys;
269     std::vector<uint8_t> protectedHeader;
270     cppbor::Map coseEncryptUnProtectedHeader;
271     std::vector<uint8_t> signature;
272     std::vector<uint8_t> diceCertChain;
273     std::vector<uint8_t> udsCertChain;
274     cppbor::Array payLoad;
275 
276     auto ret = beginSendData(keysToSign, challenge, &deviceInfo, &csrPayloadSchemaVersion,
277                              &certificateType);
278     if (!ret.isOk()) return ret;
279 
280     ret = updateMacedKey(keysToSign, coseKeys);
281     if (!ret.isOk()) return ret;
282 
283     ret = finishSendData(protectedHeader, signature, version, respFlag);
284     if (!ret.isOk()) return ret;
285 
286     ret = getUdsCertsChain(udsCertChain);
287     if (!ret.isOk()) return ret;
288 
289     ret = getDiceCertChain(diceCertChain);
290     if (!ret.isOk()) return ret;
291 
292     auto payload = cppbor::Array()
293                        .add(csrPayloadSchemaVersion)
294                        .add(certificateType)
295                        .add(EncodedItem(deviceInfo.deviceInfo))  // deviceinfo
296                        .add(std::move(coseKeys))                 // KeysToSign
297                        .encode();
298 
299     auto signDataPayload = cppbor::Array()
300                                .add(challenge)  // Challenge
301                                .add(std::move(payload))
302                                .encode();
303 
304     auto signedData = cppbor::Array()
305                           .add(std::move(protectedHeader))
306                           .add(cppbor::Map() /* unprotected parameters */)
307                           .add(std::move(signDataPayload))
308                           .add(std::move(signature));
309 
310     *csr = cppbor::Array()
311                .add(version)
312                .add(EncodedItem(udsCertChain))
313                .add(EncodedItem(diceCertChain))
314                .add(std::move(signedData))
315                .encode();
316 
317     return ScopedAStatus::ok();
318 }
319 
320 }  // namespace aidl::android::hardware::security::keymint
321