1 /*
2 * Copyright (c) 2019, 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 #include <iomanip>
18 #include <iterator>
19 #include <memory>
20 #include <set>
21 #include <string>
22 #include <tuple>
23 #include "aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.h"
24
25 #include <aidl/android/hardware/security/keymint/RpcHardwareInfo.h>
26 #include <android-base/macros.h>
27 #include <android-base/properties.h>
28 #include <cppbor.h>
29 #include <hwtrust/hwtrust.h>
30 #include <json/json.h>
31 #include <keymaster/km_openssl/ec_key.h>
32 #include <keymaster/km_openssl/ecdsa_operation.h>
33 #include <keymaster/km_openssl/openssl_err.h>
34 #include <keymaster/km_openssl/openssl_utils.h>
35 #include <openssl/base64.h>
36 #include <openssl/evp.h>
37 #include <openssl/rand.h>
38 #include <openssl/x509.h>
39 #include <remote_prov/remote_prov_utils.h>
40
41 namespace aidl::android::hardware::security::keymint::remote_prov {
42
43 constexpr uint32_t kBccPayloadIssuer = 1;
44 constexpr uint32_t kBccPayloadSubject = 2;
45 constexpr int32_t kBccPayloadSubjPubKey = -4670552;
46 constexpr int32_t kBccPayloadKeyUsage = -4670553;
47 constexpr int kP256AffinePointSize = 32;
48 constexpr uint32_t kNumTeeDeviceInfoEntries = 14;
49
50 using EC_KEY_Ptr = bssl::UniquePtr<EC_KEY>;
51 using EVP_PKEY_Ptr = bssl::UniquePtr<EVP_PKEY>;
52 using EVP_PKEY_CTX_Ptr = bssl::UniquePtr<EVP_PKEY_CTX>;
53 using X509_Ptr = bssl::UniquePtr<X509>;
54 using CRYPTO_BUFFER_Ptr = bssl::UniquePtr<CRYPTO_BUFFER>;
55
ecKeyGetPrivateKey(const EC_KEY * ecKey)56 ErrMsgOr<bytevec> ecKeyGetPrivateKey(const EC_KEY* ecKey) {
57 // Extract private key.
58 const BIGNUM* bignum = EC_KEY_get0_private_key(ecKey);
59 if (bignum == nullptr) {
60 return "Error getting bignum from private key";
61 }
62 // Pad with zeros in case the length is lesser than 32.
63 bytevec privKey(32, 0);
64 BN_bn2binpad(bignum, privKey.data(), privKey.size());
65 return privKey;
66 }
67
ecKeyGetPublicKey(const EC_KEY * ecKey)68 ErrMsgOr<bytevec> ecKeyGetPublicKey(const EC_KEY* ecKey) {
69 // Extract public key.
70 auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
71 if (group.get() == nullptr) {
72 return "Error creating EC group by curve name";
73 }
74 const EC_POINT* point = EC_KEY_get0_public_key(ecKey);
75 if (point == nullptr) return "Error getting ecpoint from public key";
76
77 int size =
78 EC_POINT_point2oct(group.get(), point, POINT_CONVERSION_UNCOMPRESSED, nullptr, 0, nullptr);
79 if (size == 0) {
80 return "Error generating public key encoding";
81 }
82
83 bytevec publicKey;
84 publicKey.resize(size);
85 EC_POINT_point2oct(group.get(), point, POINT_CONVERSION_UNCOMPRESSED, publicKey.data(),
86 publicKey.size(), nullptr);
87 return publicKey;
88 }
89
getAffineCoordinates(const bytevec & pubKey)90 ErrMsgOr<std::tuple<bytevec, bytevec>> getAffineCoordinates(const bytevec& pubKey) {
91 auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
92 if (group.get() == nullptr) {
93 return "Error creating EC group by curve name";
94 }
95 auto point = EC_POINT_Ptr(EC_POINT_new(group.get()));
96 if (EC_POINT_oct2point(group.get(), point.get(), pubKey.data(), pubKey.size(), nullptr) != 1) {
97 return "Error decoding publicKey";
98 }
99 BIGNUM_Ptr x(BN_new());
100 BIGNUM_Ptr y(BN_new());
101 BN_CTX_Ptr ctx(BN_CTX_new());
102 if (!ctx.get()) return "Failed to create BN_CTX instance";
103
104 if (!EC_POINT_get_affine_coordinates_GFp(group.get(), point.get(), x.get(), y.get(),
105 ctx.get())) {
106 return "Failed to get affine coordinates from ECPoint";
107 }
108 bytevec pubX(kP256AffinePointSize);
109 bytevec pubY(kP256AffinePointSize);
110 if (BN_bn2binpad(x.get(), pubX.data(), kP256AffinePointSize) != kP256AffinePointSize) {
111 return "Error in converting absolute value of x coordinate to big-endian";
112 }
113 if (BN_bn2binpad(y.get(), pubY.data(), kP256AffinePointSize) != kP256AffinePointSize) {
114 return "Error in converting absolute value of y coordinate to big-endian";
115 }
116 return std::make_tuple(std::move(pubX), std::move(pubY));
117 }
118
getRawPublicKey(const EVP_PKEY_Ptr & pubKey)119 ErrMsgOr<bytevec> getRawPublicKey(const EVP_PKEY_Ptr& pubKey) {
120 if (pubKey.get() == nullptr) {
121 return "pkey is null.";
122 }
123 int keyType = EVP_PKEY_base_id(pubKey.get());
124 switch (keyType) {
125 case EVP_PKEY_EC: {
126 auto ecKey = EC_KEY_Ptr(EVP_PKEY_get1_EC_KEY(pubKey.get()));
127 if (ecKey.get() == nullptr) {
128 return "Failed to get ec key";
129 }
130 return ecKeyGetPublicKey(ecKey.get());
131 }
132 case EVP_PKEY_ED25519: {
133 bytevec rawPubKey;
134 size_t rawKeySize = 0;
135 if (!EVP_PKEY_get_raw_public_key(pubKey.get(), NULL, &rawKeySize)) {
136 return "Failed to get raw public key.";
137 }
138 rawPubKey.resize(rawKeySize);
139 if (!EVP_PKEY_get_raw_public_key(pubKey.get(), rawPubKey.data(), &rawKeySize)) {
140 return "Failed to get raw public key.";
141 }
142 return rawPubKey;
143 }
144 default:
145 return "Unknown key type.";
146 }
147 }
148
generateEc256KeyPair()149 ErrMsgOr<std::tuple<bytevec, bytevec>> generateEc256KeyPair() {
150 auto ec_key = EC_KEY_Ptr(EC_KEY_new());
151 if (ec_key.get() == nullptr) {
152 return "Failed to allocate ec key";
153 }
154
155 auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
156 if (group.get() == nullptr) {
157 return "Error creating EC group by curve name";
158 }
159
160 if (EC_KEY_set_group(ec_key.get(), group.get()) != 1 ||
161 EC_KEY_generate_key(ec_key.get()) != 1 || EC_KEY_check_key(ec_key.get()) < 0) {
162 return "Error generating key";
163 }
164
165 auto privKey = ecKeyGetPrivateKey(ec_key.get());
166 if (!privKey) return privKey.moveMessage();
167
168 auto pubKey = ecKeyGetPublicKey(ec_key.get());
169 if (!pubKey) return pubKey.moveMessage();
170
171 return std::make_tuple(pubKey.moveValue(), privKey.moveValue());
172 }
173
generateX25519KeyPair()174 ErrMsgOr<std::tuple<bytevec, bytevec>> generateX25519KeyPair() {
175 /* Generate X25519 key pair */
176 bytevec pubKey(X25519_PUBLIC_VALUE_LEN);
177 bytevec privKey(X25519_PRIVATE_KEY_LEN);
178 X25519_keypair(pubKey.data(), privKey.data());
179 return std::make_tuple(std::move(pubKey), std::move(privKey));
180 }
181
generateED25519KeyPair()182 ErrMsgOr<std::tuple<bytevec, bytevec>> generateED25519KeyPair() {
183 /* Generate ED25519 key pair */
184 bytevec pubKey(ED25519_PUBLIC_KEY_LEN);
185 bytevec privKey(ED25519_PRIVATE_KEY_LEN);
186 ED25519_keypair(pubKey.data(), privKey.data());
187 return std::make_tuple(std::move(pubKey), std::move(privKey));
188 }
189
generateKeyPair(int32_t supportedEekCurve,bool isEek)190 ErrMsgOr<std::tuple<bytevec, bytevec>> generateKeyPair(int32_t supportedEekCurve, bool isEek) {
191 switch (supportedEekCurve) {
192 case RpcHardwareInfo::CURVE_25519:
193 if (isEek) {
194 return generateX25519KeyPair();
195 }
196 return generateED25519KeyPair();
197 case RpcHardwareInfo::CURVE_P256:
198 return generateEc256KeyPair();
199 default:
200 return "Unknown EEK Curve.";
201 }
202 }
203
constructCoseKey(int32_t supportedEekCurve,const bytevec & eekId,const bytevec & pubKey)204 ErrMsgOr<bytevec> constructCoseKey(int32_t supportedEekCurve, const bytevec& eekId,
205 const bytevec& pubKey) {
206 CoseKeyType keyType;
207 CoseKeyAlgorithm algorithm;
208 CoseKeyCurve curve;
209 bytevec pubX;
210 bytevec pubY;
211 switch (supportedEekCurve) {
212 case RpcHardwareInfo::CURVE_25519:
213 keyType = OCTET_KEY_PAIR;
214 algorithm = (eekId.empty()) ? EDDSA : ECDH_ES_HKDF_256;
215 curve = (eekId.empty()) ? ED25519 : cppcose::X25519;
216 pubX = pubKey;
217 break;
218 case RpcHardwareInfo::CURVE_P256: {
219 keyType = EC2;
220 algorithm = (eekId.empty()) ? ES256 : ECDH_ES_HKDF_256;
221 curve = P256;
222 auto affineCoordinates = getAffineCoordinates(pubKey);
223 if (!affineCoordinates) return affineCoordinates.moveMessage();
224 std::tie(pubX, pubY) = affineCoordinates.moveValue();
225 } break;
226 default:
227 return "Unknown EEK Curve.";
228 }
229 cppbor::Map coseKey = cppbor::Map()
230 .add(CoseKey::KEY_TYPE, keyType)
231 .add(CoseKey::ALGORITHM, algorithm)
232 .add(CoseKey::CURVE, curve)
233 .add(CoseKey::PUBKEY_X, pubX);
234
235 if (!pubY.empty()) coseKey.add(CoseKey::PUBKEY_Y, pubY);
236 if (!eekId.empty()) coseKey.add(CoseKey::KEY_ID, eekId);
237
238 return coseKey.canonicalize().encode();
239 }
240
241 bytevec kTestMacKey(32 /* count */, 0 /* byte value */);
242
randomBytes(size_t numBytes)243 bytevec randomBytes(size_t numBytes) {
244 bytevec retval(numBytes);
245 RAND_bytes(retval.data(), numBytes);
246 return retval;
247 }
248
constructCoseSign1(int32_t supportedEekCurve,const bytevec & key,const bytevec & payload,const bytevec & aad)249 ErrMsgOr<cppbor::Array> constructCoseSign1(int32_t supportedEekCurve, const bytevec& key,
250 const bytevec& payload, const bytevec& aad) {
251 if (supportedEekCurve == RpcHardwareInfo::CURVE_P256) {
252 return constructECDSACoseSign1(key, {} /* protectedParams */, payload, aad);
253 } else {
254 return cppcose::constructCoseSign1(key, payload, aad);
255 }
256 }
257
generateEekChain(int32_t supportedEekCurve,size_t length,const bytevec & eekId)258 ErrMsgOr<EekChain> generateEekChain(int32_t supportedEekCurve, size_t length,
259 const bytevec& eekId) {
260 if (length < 2) {
261 return "EEK chain must contain at least 2 certs.";
262 }
263
264 auto eekChain = cppbor::Array();
265
266 bytevec prev_priv_key;
267 for (size_t i = 0; i < length - 1; ++i) {
268 auto keyPair = generateKeyPair(supportedEekCurve, false);
269 if (!keyPair) return keyPair.moveMessage();
270 auto [pub_key, priv_key] = keyPair.moveValue();
271
272 // The first signing key is self-signed.
273 if (prev_priv_key.empty()) prev_priv_key = priv_key;
274
275 auto coseKey = constructCoseKey(supportedEekCurve, {}, pub_key);
276 if (!coseKey) return coseKey.moveMessage();
277
278 auto coseSign1 =
279 constructCoseSign1(supportedEekCurve, prev_priv_key, coseKey.moveValue(), {} /* AAD */);
280 if (!coseSign1) return coseSign1.moveMessage();
281 eekChain.add(coseSign1.moveValue());
282
283 prev_priv_key = priv_key;
284 }
285 auto keyPair = generateKeyPair(supportedEekCurve, true);
286 if (!keyPair) return keyPair.moveMessage();
287 auto [pub_key, priv_key] = keyPair.moveValue();
288
289 auto coseKey = constructCoseKey(supportedEekCurve, eekId, pub_key);
290 if (!coseKey) return coseKey.moveMessage();
291
292 auto coseSign1 =
293 constructCoseSign1(supportedEekCurve, prev_priv_key, coseKey.moveValue(), {} /* AAD */);
294 if (!coseSign1) return coseSign1.moveMessage();
295 eekChain.add(coseSign1.moveValue());
296
297 if (supportedEekCurve == RpcHardwareInfo::CURVE_P256) {
298 // convert ec public key to x and y co-ordinates.
299 auto affineCoordinates = getAffineCoordinates(pub_key);
300 if (!affineCoordinates) return affineCoordinates.moveMessage();
301 auto [pubX, pubY] = affineCoordinates.moveValue();
302 pub_key.clear();
303 pub_key.insert(pub_key.begin(), pubX.begin(), pubX.end());
304 pub_key.insert(pub_key.end(), pubY.begin(), pubY.end());
305 }
306
307 return EekChain{eekChain.encode(), pub_key, priv_key};
308 }
309
getProdEekChain(int32_t supportedEekCurve)310 bytevec getProdEekChain(int32_t supportedEekCurve) {
311 cppbor::Array chain;
312 if (supportedEekCurve == RpcHardwareInfo::CURVE_P256) {
313 chain.add(cppbor::EncodedItem(bytevec(std::begin(kCoseEncodedEcdsa256RootCert),
314 std::end(kCoseEncodedEcdsa256RootCert))));
315 chain.add(cppbor::EncodedItem(bytevec(std::begin(kCoseEncodedEcdsa256GeekCert),
316 std::end(kCoseEncodedEcdsa256GeekCert))));
317 } else {
318 chain.add(cppbor::EncodedItem(
319 bytevec(std::begin(kCoseEncodedRootCert), std::end(kCoseEncodedRootCert))));
320 chain.add(cppbor::EncodedItem(
321 bytevec(std::begin(kCoseEncodedGeekCert), std::end(kCoseEncodedGeekCert))));
322 }
323 return chain.encode();
324 }
325
validateBcc(const cppbor::Array * bcc,hwtrust::DiceChain::Kind kind)326 ErrMsgOr<std::vector<BccEntryData>> validateBcc(const cppbor::Array* bcc,
327 hwtrust::DiceChain::Kind kind) {
328 auto encodedBcc = bcc->encode();
329 auto chain = hwtrust::DiceChain::Verify(encodedBcc, kind);
330 if (!chain.ok()) return chain.error().message();
331 auto keys = chain->CosePublicKeys();
332 if (!keys.ok()) return keys.error().message();
333 std::vector<BccEntryData> result;
334 for (auto& key : *keys) {
335 result.push_back({std::move(key)});
336 }
337 return result;
338 }
339
jsonEncodeCsrWithBuild(const std::string & instance_name,const cppbor::Array & csr,const std::string & serialno_prop)340 JsonOutput jsonEncodeCsrWithBuild(const std::string& instance_name, const cppbor::Array& csr,
341 const std::string& serialno_prop) {
342 const std::string kFingerprintProp = "ro.build.fingerprint";
343
344 if (!::android::base::WaitForPropertyCreation(kFingerprintProp)) {
345 return JsonOutput::Error("Unable to read build fingerprint");
346 }
347
348 bytevec csrCbor = csr.encode();
349 size_t base64Length;
350 int rc = EVP_EncodedLength(&base64Length, csrCbor.size());
351 if (!rc) {
352 return JsonOutput::Error("Error getting base64 length. Size overflow?");
353 }
354
355 std::vector<char> base64(base64Length);
356 rc = EVP_EncodeBlock(reinterpret_cast<uint8_t*>(base64.data()), csrCbor.data(), csrCbor.size());
357 ++rc; // Account for NUL, which BoringSSL does not for some reason.
358 if (rc != base64Length) {
359 return JsonOutput::Error("Error writing base64. Expected " + std::to_string(base64Length) +
360 " bytes to be written, but " + std::to_string(rc) +
361 " bytes were actually written.");
362 }
363
364 Json::Value json(Json::objectValue);
365 json["name"] = instance_name;
366 json["build_fingerprint"] = ::android::base::GetProperty(kFingerprintProp, /*default=*/"");
367 json["serialno"] = ::android::base::GetProperty(serialno_prop, /*default=*/"");
368 json["csr"] = base64.data(); // Boring writes a NUL-terminated c-string
369
370 Json::StreamWriterBuilder factory;
371 factory["indentation"] = ""; // disable pretty formatting
372 return JsonOutput::Ok(Json::writeString(factory, json));
373 }
374
checkMapEntry(bool isFactory,const cppbor::Map & devInfo,cppbor::MajorType majorType,const std::string & entryName)375 std::string checkMapEntry(bool isFactory, const cppbor::Map& devInfo, cppbor::MajorType majorType,
376 const std::string& entryName) {
377 const std::unique_ptr<cppbor::Item>& val = devInfo.get(entryName);
378 if (!val) {
379 return entryName + " is missing.\n";
380 }
381 if (val->type() != majorType) {
382 return entryName + " has the wrong type.\n";
383 }
384 if (isFactory) {
385 return "";
386 }
387 switch (majorType) {
388 case cppbor::TSTR:
389 if (val->asTstr()->value().size() <= 0) {
390 return entryName + " is present but the value is empty.\n";
391 }
392 break;
393 case cppbor::BSTR:
394 if (val->asBstr()->value().size() <= 0) {
395 return entryName + " is present but the value is empty.\n";
396 }
397 break;
398 default:
399 break;
400 }
401 return "";
402 }
403
checkMapEntry(bool isFactory,const cppbor::Map & devInfo,cppbor::MajorType majorType,const std::string & entryName,const cppbor::Array & allowList)404 std::string checkMapEntry(bool isFactory, const cppbor::Map& devInfo, cppbor::MajorType majorType,
405 const std::string& entryName, const cppbor::Array& allowList) {
406 std::string error = checkMapEntry(isFactory, devInfo, majorType, entryName);
407 if (!error.empty()) {
408 return error;
409 }
410
411 if (isFactory) {
412 return "";
413 }
414
415 const std::unique_ptr<cppbor::Item>& val = devInfo.get(entryName);
416 for (auto i = allowList.begin(); i != allowList.end(); ++i) {
417 if (**i == *val) {
418 return "";
419 }
420 }
421 return entryName + " has an invalid value.\n";
422 }
423
checkMapPatchLevelEntry(bool isFactory,const cppbor::Map & devInfo,const std::string & entryName)424 std::string checkMapPatchLevelEntry(bool isFactory, const cppbor::Map& devInfo,
425 const std::string& entryName) {
426 std::string error = checkMapEntry(isFactory, devInfo, cppbor::UINT, entryName);
427 if (!error.empty()) {
428 return error;
429 }
430
431 if (isFactory) {
432 return "";
433 }
434
435 const std::unique_ptr<cppbor::Item>& val = devInfo.get(entryName);
436 std::string dateString = std::to_string(val->asUint()->unsignedValue());
437 if (dateString.size() == 6) {
438 dateString += "01";
439 }
440 if (dateString.size() != 8) {
441 return entryName + " should in the format YYYYMMDD or YYYYMM\n";
442 }
443
444 std::tm t;
445 std::istringstream ss(dateString);
446 ss >> std::get_time(&t, "%Y%m%d");
447 if (!ss) {
448 return entryName + " should in the format YYYYMMDD or YYYYMM\n";
449 }
450
451 return "";
452 }
453
isTeeDeviceInfo(const cppbor::Map & devInfo)454 bool isTeeDeviceInfo(const cppbor::Map& devInfo) {
455 return devInfo.get("security_level") && devInfo.get("security_level")->asTstr() &&
456 devInfo.get("security_level")->asTstr()->value() == "tee";
457 }
458
parseAndValidateDeviceInfo(const std::vector<uint8_t> & deviceInfoBytes,IRemotelyProvisionedComponent * provisionable,bool isFactory)459 ErrMsgOr<std::unique_ptr<cppbor::Map>> parseAndValidateDeviceInfo(
460 const std::vector<uint8_t>& deviceInfoBytes, IRemotelyProvisionedComponent* provisionable,
461 bool isFactory) {
462 const cppbor::Array kValidVbStates = {"green", "yellow", "orange"};
463 const cppbor::Array kValidBootloaderStates = {"locked", "unlocked"};
464 const cppbor::Array kValidSecurityLevels = {"tee", "strongbox"};
465 const cppbor::Array kValidAttIdStates = {"locked", "open"};
466 const cppbor::Array kValidFused = {0, 1};
467 constexpr std::array<std::string_view, kNumTeeDeviceInfoEntries> kDeviceInfoKeys = {
468 "brand",
469 "manufacturer",
470 "product",
471 "model",
472 "device",
473 "vb_state",
474 "bootloader_state",
475 "vbmeta_digest",
476 "os_version",
477 "system_patch_level",
478 "boot_patch_level",
479 "vendor_patch_level",
480 "security_level",
481 "fused"};
482
483 struct AttestationIdEntry {
484 const char* id;
485 bool alwaysValidate;
486 };
487 constexpr AttestationIdEntry kAttestationIdEntrySet[] = {{"brand", false},
488 {"manufacturer", true},
489 {"product", false},
490 {"model", false},
491 {"device", false}};
492
493 auto [parsedVerifiedDeviceInfo, ignore1, errMsg] = cppbor::parse(deviceInfoBytes);
494 if (!parsedVerifiedDeviceInfo) {
495 return errMsg;
496 }
497
498 std::unique_ptr<cppbor::Map> parsed(parsedVerifiedDeviceInfo.release()->asMap());
499 if (!parsed) {
500 return "DeviceInfo must be a CBOR map.";
501 }
502
503 if (parsed->clone()->asMap()->canonicalize().encode() != deviceInfoBytes) {
504 return "DeviceInfo ordering is non-canonical.";
505 }
506
507 RpcHardwareInfo info;
508 provisionable->getHardwareInfo(&info);
509 if (info.versionNumber < 3) {
510 const std::unique_ptr<cppbor::Item>& version = parsed->get("version");
511 if (!version) {
512 return "Device info is missing version";
513 }
514 if (!version->asUint()) {
515 return "version must be an unsigned integer";
516 }
517 if (version->asUint()->value() != info.versionNumber) {
518 return "DeviceInfo version (" + std::to_string(version->asUint()->value()) +
519 ") does not match the remotely provisioned component version (" +
520 std::to_string(info.versionNumber) + ").";
521 }
522 }
523 // Bypasses the device info validation since the device info in AVF is currently
524 // empty. Check b/299256925 for more information.
525 //
526 // TODO(b/300911665): This check is temporary and will be replaced once the markers
527 // on the DICE chain become available. We need to determine if the CSR is from the
528 // RKP VM using the markers on the DICE chain.
529 if (info.uniqueId == "AVF Remote Provisioning 1") {
530 return std::move(parsed);
531 }
532
533 std::string error;
534 std::string tmp;
535 std::set<std::string_view> previousKeys;
536 switch (info.versionNumber) {
537 case 3:
538 if (isTeeDeviceInfo(*parsed) && parsed->size() != kNumTeeDeviceInfoEntries) {
539 error += fmt::format(
540 "Err: Incorrect number of device info entries. Expected {} but got "
541 "{}\n",
542 kNumTeeDeviceInfoEntries, parsed->size());
543 }
544 // TEE IRPC instances require all entries to be present in DeviceInfo. Non-TEE instances
545 // may omit `os_version`
546 if (!isTeeDeviceInfo(*parsed) && (parsed->size() != kNumTeeDeviceInfoEntries &&
547 parsed->size() != kNumTeeDeviceInfoEntries - 1)) {
548 error += fmt::format(
549 "Err: Incorrect number of device info entries. Expected {} or {} but got "
550 "{}\n",
551 kNumTeeDeviceInfoEntries - 1, kNumTeeDeviceInfoEntries, parsed->size());
552 }
553 for (auto& [key, _] : *parsed) {
554 const std::string& keyValue = key->asTstr()->value();
555 if (!previousKeys.insert(keyValue).second) {
556 error += "Err: Duplicate device info entry: <" + keyValue + ">,\n";
557 }
558 if (std::find(kDeviceInfoKeys.begin(), kDeviceInfoKeys.end(), keyValue) ==
559 kDeviceInfoKeys.end()) {
560 error += "Err: Unrecognized key entry: <" + key->asTstr()->value() + ">,\n";
561 }
562 }
563 // Checks that only apply to v3.
564 error += checkMapPatchLevelEntry(isFactory, *parsed, "system_patch_level");
565 error += checkMapPatchLevelEntry(isFactory, *parsed, "boot_patch_level");
566 error += checkMapPatchLevelEntry(isFactory, *parsed, "vendor_patch_level");
567 FALLTHROUGH_INTENDED;
568 case 2:
569 for (const auto& entry : kAttestationIdEntrySet) {
570 tmp = checkMapEntry(isFactory && !entry.alwaysValidate, *parsed, cppbor::TSTR,
571 entry.id);
572 }
573 if (!tmp.empty()) {
574 error += tmp +
575 "Attestation IDs are missing or malprovisioned. If this test is being\n"
576 "run against an early proto or EVT build, this error is probably WAI\n"
577 "and indicates that Device IDs were not provisioned in the factory. If\n"
578 "this error is returned on a DVT or later build revision, then\n"
579 "something is likely wrong with the factory provisioning process.";
580 }
581 // TODO: Refactor the KeyMint code that validates these fields and include it here.
582 error += checkMapEntry(isFactory, *parsed, cppbor::TSTR, "vb_state", kValidVbStates);
583 error += checkMapEntry(isFactory, *parsed, cppbor::TSTR, "bootloader_state",
584 kValidBootloaderStates);
585 error += checkMapEntry(isFactory, *parsed, cppbor::BSTR, "vbmeta_digest");
586 error += checkMapEntry(isFactory, *parsed, cppbor::UINT, "system_patch_level");
587 error += checkMapEntry(isFactory, *parsed, cppbor::UINT, "boot_patch_level");
588 error += checkMapEntry(isFactory, *parsed, cppbor::UINT, "vendor_patch_level");
589 error += checkMapEntry(isFactory, *parsed, cppbor::UINT, "fused", kValidFused);
590 error += checkMapEntry(isFactory, *parsed, cppbor::TSTR, "security_level",
591 kValidSecurityLevels);
592 if (isTeeDeviceInfo(*parsed)) {
593 error += checkMapEntry(isFactory, *parsed, cppbor::TSTR, "os_version");
594 }
595 break;
596 case 1:
597 error += checkMapEntry(isFactory, *parsed, cppbor::TSTR, "security_level",
598 kValidSecurityLevels);
599 error += checkMapEntry(isFactory, *parsed, cppbor::TSTR, "att_id_state",
600 kValidAttIdStates);
601 break;
602 default:
603 return "Unrecognized version: " + std::to_string(info.versionNumber);
604 }
605
606 if (!error.empty()) {
607 return error;
608 }
609
610 return std::move(parsed);
611 }
612
parseAndValidateFactoryDeviceInfo(const std::vector<uint8_t> & deviceInfoBytes,IRemotelyProvisionedComponent * provisionable)613 ErrMsgOr<std::unique_ptr<cppbor::Map>> parseAndValidateFactoryDeviceInfo(
614 const std::vector<uint8_t>& deviceInfoBytes, IRemotelyProvisionedComponent* provisionable) {
615 return parseAndValidateDeviceInfo(deviceInfoBytes, provisionable, /*isFactory=*/true);
616 }
617
parseAndValidateProductionDeviceInfo(const std::vector<uint8_t> & deviceInfoBytes,IRemotelyProvisionedComponent * provisionable)618 ErrMsgOr<std::unique_ptr<cppbor::Map>> parseAndValidateProductionDeviceInfo(
619 const std::vector<uint8_t>& deviceInfoBytes, IRemotelyProvisionedComponent* provisionable) {
620 return parseAndValidateDeviceInfo(deviceInfoBytes, provisionable, /*isFactory=*/false);
621 }
622
getSessionKey(ErrMsgOr<std::pair<bytevec,bytevec>> & senderPubkey,const EekChain & eekChain,int32_t supportedEekCurve)623 ErrMsgOr<bytevec> getSessionKey(ErrMsgOr<std::pair<bytevec, bytevec>>& senderPubkey,
624 const EekChain& eekChain, int32_t supportedEekCurve) {
625 if (supportedEekCurve == RpcHardwareInfo::CURVE_25519 ||
626 supportedEekCurve == RpcHardwareInfo::CURVE_NONE) {
627 return x25519_HKDF_DeriveKey(eekChain.last_pubkey, eekChain.last_privkey,
628 senderPubkey->first, false /* senderIsA */);
629 } else {
630 return ECDH_HKDF_DeriveKey(eekChain.last_pubkey, eekChain.last_privkey, senderPubkey->first,
631 false /* senderIsA */);
632 }
633 }
634
verifyProtectedData(const DeviceInfo & deviceInfo,const cppbor::Array & keysToSign,const std::vector<uint8_t> & keysToSignMac,const ProtectedData & protectedData,const EekChain & eekChain,const std::vector<uint8_t> & eekId,int32_t supportedEekCurve,IRemotelyProvisionedComponent * provisionable,const std::vector<uint8_t> & challenge,bool isFactory)635 ErrMsgOr<std::vector<BccEntryData>> verifyProtectedData(
636 const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign,
637 const std::vector<uint8_t>& keysToSignMac, const ProtectedData& protectedData,
638 const EekChain& eekChain, const std::vector<uint8_t>& eekId, int32_t supportedEekCurve,
639 IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge,
640 bool isFactory) {
641 auto [parsedProtectedData, _, protDataErrMsg] = cppbor::parse(protectedData.protectedData);
642 if (!parsedProtectedData) {
643 return protDataErrMsg;
644 }
645 if (!parsedProtectedData->asArray()) {
646 return "Protected data is not a CBOR array.";
647 }
648 if (parsedProtectedData->asArray()->size() != kCoseEncryptEntryCount) {
649 return "The protected data COSE_encrypt structure must have " +
650 std::to_string(kCoseEncryptEntryCount) + " entries, but it only has " +
651 std::to_string(parsedProtectedData->asArray()->size());
652 }
653
654 auto senderPubkey = getSenderPubKeyFromCoseEncrypt(parsedProtectedData);
655 if (!senderPubkey) {
656 return senderPubkey.message();
657 }
658 if (senderPubkey->second != eekId) {
659 return "The COSE_encrypt recipient does not match the expected EEK identifier";
660 }
661
662 auto sessionKey = getSessionKey(senderPubkey, eekChain, supportedEekCurve);
663 if (!sessionKey) {
664 return sessionKey.message();
665 }
666
667 auto protectedDataPayload =
668 decryptCoseEncrypt(*sessionKey, parsedProtectedData.get(), bytevec{} /* aad */);
669 if (!protectedDataPayload) {
670 return protectedDataPayload.message();
671 }
672
673 auto [parsedPayload, __, payloadErrMsg] = cppbor::parse(*protectedDataPayload);
674 if (!parsedPayload) {
675 return "Failed to parse payload: " + payloadErrMsg;
676 }
677 if (!parsedPayload->asArray()) {
678 return "The protected data payload must be an Array.";
679 }
680 if (parsedPayload->asArray()->size() != 3U && parsedPayload->asArray()->size() != 2U) {
681 return "The protected data payload must contain SignedMAC and BCC. It may optionally "
682 "contain AdditionalDKSignatures. However, the parsed payload has " +
683 std::to_string(parsedPayload->asArray()->size()) + " entries.";
684 }
685
686 auto& signedMac = parsedPayload->asArray()->get(0);
687 auto& bcc = parsedPayload->asArray()->get(1);
688 if (!signedMac->asArray()) {
689 return "The SignedMAC in the protected data payload is not an Array.";
690 }
691 if (!bcc->asArray()) {
692 return "The BCC in the protected data payload is not an Array.";
693 }
694
695 // BCC is [ pubkey, + BccEntry]
696 auto bccContents = validateBcc(bcc->asArray(), hwtrust::DiceChain::Kind::kVsr13);
697 if (!bccContents) {
698 return bccContents.message() + "\n" + prettyPrint(bcc.get());
699 }
700
701 auto deviceInfoResult =
702 parseAndValidateDeviceInfo(deviceInfo.deviceInfo, provisionable, isFactory);
703 if (!deviceInfoResult) {
704 return deviceInfoResult.message();
705 }
706 std::unique_ptr<cppbor::Map> deviceInfoMap = deviceInfoResult.moveValue();
707 auto& signingKey = bccContents->back().pubKey;
708 auto macKey = verifyAndParseCoseSign1(signedMac->asArray(), signingKey,
709 cppbor::Array() // SignedMacAad
710 .add(challenge)
711 .add(std::move(deviceInfoMap))
712 .add(keysToSignMac)
713 .encode());
714 if (!macKey) {
715 return macKey.message();
716 }
717
718 auto coseMac0 = cppbor::Array()
719 .add(cppbor::Map() // protected
720 .add(ALGORITHM, HMAC_256)
721 .canonicalize()
722 .encode())
723 .add(cppbor::Map()) // unprotected
724 .add(keysToSign.encode()) // payload (keysToSign)
725 .add(keysToSignMac); // tag
726
727 auto macPayload = verifyAndParseCoseMac0(&coseMac0, *macKey);
728 if (!macPayload) {
729 return macPayload.message();
730 }
731
732 return *bccContents;
733 }
734
verifyFactoryProtectedData(const DeviceInfo & deviceInfo,const cppbor::Array & keysToSign,const std::vector<uint8_t> & keysToSignMac,const ProtectedData & protectedData,const EekChain & eekChain,const std::vector<uint8_t> & eekId,int32_t supportedEekCurve,IRemotelyProvisionedComponent * provisionable,const std::vector<uint8_t> & challenge)735 ErrMsgOr<std::vector<BccEntryData>> verifyFactoryProtectedData(
736 const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign,
737 const std::vector<uint8_t>& keysToSignMac, const ProtectedData& protectedData,
738 const EekChain& eekChain, const std::vector<uint8_t>& eekId, int32_t supportedEekCurve,
739 IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge) {
740 return verifyProtectedData(deviceInfo, keysToSign, keysToSignMac, protectedData, eekChain,
741 eekId, supportedEekCurve, provisionable, challenge,
742 /*isFactory=*/true);
743 }
744
verifyProductionProtectedData(const DeviceInfo & deviceInfo,const cppbor::Array & keysToSign,const std::vector<uint8_t> & keysToSignMac,const ProtectedData & protectedData,const EekChain & eekChain,const std::vector<uint8_t> & eekId,int32_t supportedEekCurve,IRemotelyProvisionedComponent * provisionable,const std::vector<uint8_t> & challenge)745 ErrMsgOr<std::vector<BccEntryData>> verifyProductionProtectedData(
746 const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign,
747 const std::vector<uint8_t>& keysToSignMac, const ProtectedData& protectedData,
748 const EekChain& eekChain, const std::vector<uint8_t>& eekId, int32_t supportedEekCurve,
749 IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge) {
750 return verifyProtectedData(deviceInfo, keysToSign, keysToSignMac, protectedData, eekChain,
751 eekId, supportedEekCurve, provisionable, challenge,
752 /*isFactory=*/false);
753 }
754
parseX509Cert(const std::vector<uint8_t> & cert)755 ErrMsgOr<X509_Ptr> parseX509Cert(const std::vector<uint8_t>& cert) {
756 CRYPTO_BUFFER_Ptr certBuf(CRYPTO_BUFFER_new(cert.data(), cert.size(), nullptr));
757 if (!certBuf.get()) {
758 return "Failed to create crypto buffer.";
759 }
760 X509_Ptr result(X509_parse_from_buffer(certBuf.get()));
761 if (!result.get()) {
762 return "Failed to parse certificate.";
763 }
764 return result;
765 }
766
getX509IssuerName(const X509_Ptr & cert)767 std::string getX509IssuerName(const X509_Ptr& cert) {
768 char* name = X509_NAME_oneline(X509_get_issuer_name(cert.get()), nullptr, 0);
769 std::string result(name);
770 OPENSSL_free(name);
771 return result;
772 }
773
getX509SubjectName(const X509_Ptr & cert)774 std::string getX509SubjectName(const X509_Ptr& cert) {
775 char* name = X509_NAME_oneline(X509_get_subject_name(cert.get()), nullptr, 0);
776 std::string result(name);
777 OPENSSL_free(name);
778 return result;
779 }
780
781 // Validates the certificate chain and returns the leaf public key.
validateCertChain(const cppbor::Array & chain)782 ErrMsgOr<bytevec> validateCertChain(const cppbor::Array& chain) {
783 bytevec rawPubKey;
784 for (size_t i = 0; i < chain.size(); ++i) {
785 // Root must be self-signed.
786 size_t signingCertIndex = (i > 0) ? i - 1 : i;
787 auto& keyCertItem = chain[i];
788 auto& signingCertItem = chain[signingCertIndex];
789 if (!keyCertItem || !keyCertItem->asBstr()) {
790 return "Key certificate must be a Bstr.";
791 }
792 if (!signingCertItem || !signingCertItem->asBstr()) {
793 return "Signing certificate must be a Bstr.";
794 }
795
796 auto keyCert = parseX509Cert(keyCertItem->asBstr()->value());
797 if (!keyCert) {
798 return keyCert.message();
799 }
800 auto signingCert = parseX509Cert(signingCertItem->asBstr()->value());
801 if (!signingCert) {
802 return signingCert.message();
803 }
804
805 EVP_PKEY_Ptr pubKey(X509_get_pubkey(keyCert->get()));
806 if (!pubKey.get()) {
807 return "Failed to get public key.";
808 }
809 EVP_PKEY_Ptr signingPubKey(X509_get_pubkey(signingCert->get()));
810 if (!signingPubKey.get()) {
811 return "Failed to get signing public key.";
812 }
813
814 if (!X509_verify(keyCert->get(), signingPubKey.get())) {
815 return "Verification of certificate " + std::to_string(i) +
816 " faile. OpenSSL error string: " + ERR_error_string(ERR_get_error(), NULL);
817 }
818
819 auto certIssuer = getX509IssuerName(*keyCert);
820 auto signerSubj = getX509SubjectName(*signingCert);
821 if (certIssuer != signerSubj) {
822 return "Certificate " + std::to_string(i) + " has wrong issuer. Signer subject is " +
823 signerSubj + " Issuer subject is " + certIssuer;
824 }
825 if (i == chain.size() - 1) {
826 auto key = getRawPublicKey(pubKey);
827 if (!key) key.moveMessage();
828 rawPubKey = key.moveValue();
829 }
830 }
831 return rawPubKey;
832 }
833
validateUdsCerts(const cppbor::Map & udsCerts,const bytevec & udsCoseKeyBytes)834 std::string validateUdsCerts(const cppbor::Map& udsCerts, const bytevec& udsCoseKeyBytes) {
835 for (const auto& [signerName, udsCertChain] : udsCerts) {
836 if (!signerName || !signerName->asTstr()) {
837 return "Signer Name must be a Tstr.";
838 }
839 if (!udsCertChain || !udsCertChain->asArray()) {
840 return "UDS certificate chain must be an Array.";
841 }
842 if (udsCertChain->asArray()->size() < 2) {
843 return "UDS certificate chain must have at least two entries: root and leaf.";
844 }
845
846 auto leafPubKey = validateCertChain(*udsCertChain->asArray());
847 if (!leafPubKey) {
848 return leafPubKey.message();
849 }
850 auto coseKey = CoseKey::parse(udsCoseKeyBytes);
851 if (!coseKey) return coseKey.moveMessage();
852
853 auto curve = coseKey->getIntValue(CoseKey::CURVE);
854 if (!curve) {
855 return "CoseKey must contain curve.";
856 }
857 bytevec udsPub;
858 if (curve == CoseKeyCurve::P256 || curve == CoseKeyCurve::P384) {
859 auto pubKey = coseKey->getEcPublicKey();
860 if (!pubKey) return pubKey.moveMessage();
861 // convert public key to uncompressed form by prepending 0x04 at begin.
862 pubKey->insert(pubKey->begin(), 0x04);
863 udsPub = pubKey.moveValue();
864 } else if (curve == CoseKeyCurve::ED25519) {
865 auto& pubkey = coseKey->getMap().get(cppcose::CoseKey::PUBKEY_X);
866 if (!pubkey || !pubkey->asBstr()) {
867 return "Invalid public key.";
868 }
869 udsPub = pubkey->asBstr()->value();
870 } else {
871 return "Unknown curve.";
872 }
873 if (*leafPubKey != udsPub) {
874 return "Leaf public key in UDS certificate chain doesn't match UDS public key.";
875 }
876 }
877 return "";
878 }
879
parseAndValidateCsrPayload(const cppbor::Array & keysToSign,const std::vector<uint8_t> & csrPayload,IRemotelyProvisionedComponent * provisionable,bool isFactory)880 ErrMsgOr<std::unique_ptr<cppbor::Array>> parseAndValidateCsrPayload(
881 const cppbor::Array& keysToSign, const std::vector<uint8_t>& csrPayload,
882 IRemotelyProvisionedComponent* provisionable, bool isFactory) {
883 auto [parsedCsrPayload, _, errMsg] = cppbor::parse(csrPayload);
884 if (!parsedCsrPayload) {
885 return errMsg;
886 }
887
888 std::unique_ptr<cppbor::Array> parsed(parsedCsrPayload.release()->asArray());
889 if (!parsed) {
890 return "CSR payload is not a CBOR array.";
891 }
892
893 if (parsed->size() != 4U) {
894 return "CSR payload must contain version, certificate type, device info, keys. "
895 "However, the parsed CSR payload has " +
896 std::to_string(parsed->size()) + " entries.";
897 }
898
899 auto signedVersion = parsed->get(0)->asUint();
900 auto signedCertificateType = parsed->get(1)->asTstr();
901 auto signedDeviceInfo = parsed->get(2)->asMap();
902 auto signedKeys = parsed->get(3)->asArray();
903
904 if (!signedVersion || signedVersion->value() != 3U) {
905 return "CSR payload version must be an unsigned integer and must be equal to 3.";
906 }
907 if (!signedCertificateType) {
908 // Certificate type is allowed to be extendend by vendor, i.e. we can't
909 // enforce its value.
910 return "Certificate type must be a Tstr.";
911 }
912 if (!signedDeviceInfo) {
913 return "Device info must be an Map.";
914 }
915 if (!signedKeys) {
916 return "Keys must be an Array.";
917 }
918
919 auto result = parseAndValidateDeviceInfo(signedDeviceInfo->encode(), provisionable, isFactory);
920 if (!result) {
921 return result.message();
922 }
923
924 if (signedKeys->encode() != keysToSign.encode()) {
925 return "Signed keys do not match.";
926 }
927
928 return std::move(parsed);
929 }
930
parseAndValidateAuthenticatedRequestSignedPayload(const std::vector<uint8_t> & signedPayload,const std::vector<uint8_t> & challenge)931 ErrMsgOr<bytevec> parseAndValidateAuthenticatedRequestSignedPayload(
932 const std::vector<uint8_t>& signedPayload, const std::vector<uint8_t>& challenge) {
933 auto [parsedSignedPayload, _, errMsg] = cppbor::parse(signedPayload);
934 if (!parsedSignedPayload) {
935 return errMsg;
936 }
937 if (!parsedSignedPayload->asArray()) {
938 return "SignedData payload is not a CBOR array.";
939 }
940 if (parsedSignedPayload->asArray()->size() != 2U) {
941 return "SignedData payload must contain the challenge and request. However, the parsed "
942 "SignedData payload has " +
943 std::to_string(parsedSignedPayload->asArray()->size()) + " entries.";
944 }
945
946 auto signedChallenge = parsedSignedPayload->asArray()->get(0)->asBstr();
947 auto signedRequest = parsedSignedPayload->asArray()->get(1)->asBstr();
948
949 if (!signedChallenge) {
950 return "Challenge must be a Bstr.";
951 }
952
953 if (challenge.size() > 64) {
954 return "Challenge size must be between 0 and 64 bytes inclusive. "
955 "However, challenge is " +
956 std::to_string(challenge.size()) + " bytes long.";
957 }
958
959 auto challengeBstr = cppbor::Bstr(challenge);
960 if (*signedChallenge != challengeBstr) {
961 return "Signed challenge does not match."
962 "\n Actual: " +
963 cppbor::prettyPrint(signedChallenge->asBstr(), 64 /* maxBStrSize */) +
964 "\nExpected: " + cppbor::prettyPrint(&challengeBstr, 64 /* maxBStrSize */);
965 }
966
967 if (!signedRequest) {
968 return "Request must be a Bstr.";
969 }
970
971 return signedRequest->value();
972 }
973
getDiceChainKind()974 ErrMsgOr<hwtrust::DiceChain::Kind> getDiceChainKind() {
975 int vendor_api_level = ::android::base::GetIntProperty("ro.vendor.api_level", -1);
976 switch (vendor_api_level) {
977 case __ANDROID_API_T__:
978 return hwtrust::DiceChain::Kind::kVsr13;
979 case __ANDROID_API_U__:
980 return hwtrust::DiceChain::Kind::kVsr14;
981 case 202404: /* TODO(b/315056516) Use a version macro for vendor API 24Q2 */
982 return hwtrust::DiceChain::Kind::kVsr15;
983 default:
984 return "Unsupported vendor API level: " + std::to_string(vendor_api_level);
985 }
986 }
987
parseAndValidateAuthenticatedRequest(const std::vector<uint8_t> & request,const std::vector<uint8_t> & challenge)988 ErrMsgOr<bytevec> parseAndValidateAuthenticatedRequest(const std::vector<uint8_t>& request,
989 const std::vector<uint8_t>& challenge) {
990 auto [parsedRequest, _, csrErrMsg] = cppbor::parse(request);
991 if (!parsedRequest) {
992 return csrErrMsg;
993 }
994 if (!parsedRequest->asArray()) {
995 return "AuthenticatedRequest is not a CBOR array.";
996 }
997 if (parsedRequest->asArray()->size() != 4U) {
998 return "AuthenticatedRequest must contain version, UDS certificates, DICE chain, and "
999 "signed data. However, the parsed AuthenticatedRequest has " +
1000 std::to_string(parsedRequest->asArray()->size()) + " entries.";
1001 }
1002
1003 auto version = parsedRequest->asArray()->get(0)->asUint();
1004 auto udsCerts = parsedRequest->asArray()->get(1)->asMap();
1005 auto diceCertChain = parsedRequest->asArray()->get(2)->asArray();
1006 auto signedData = parsedRequest->asArray()->get(3)->asArray();
1007
1008 if (!version || version->value() != 1U) {
1009 return "AuthenticatedRequest version must be an unsigned integer and must be equal to 1.";
1010 }
1011 if (!udsCerts) {
1012 return "AuthenticatedRequest UdsCerts must be an Map.";
1013 }
1014 if (!diceCertChain) {
1015 return "AuthenticatedRequest DiceCertChain must be an Array.";
1016 }
1017 if (!signedData) {
1018 return "AuthenticatedRequest SignedData must be an Array.";
1019 }
1020
1021 // DICE chain is [ pubkey, + DiceChainEntry ].
1022 auto diceChainKind = getDiceChainKind();
1023 if (!diceChainKind) {
1024 return diceChainKind.message();
1025 }
1026
1027 auto diceContents = validateBcc(diceCertChain, *diceChainKind);
1028 if (!diceContents) {
1029 return diceContents.message() + "\n" + prettyPrint(diceCertChain);
1030 }
1031
1032 auto& udsPub = diceContents->back().pubKey;
1033
1034 auto error = validateUdsCerts(*udsCerts, udsPub);
1035 if (!error.empty()) {
1036 return error;
1037 }
1038
1039 auto signedPayload = verifyAndParseCoseSign1(signedData, udsPub, {} /* aad */);
1040 if (!signedPayload) {
1041 return signedPayload.message();
1042 }
1043
1044 auto payload = parseAndValidateAuthenticatedRequestSignedPayload(*signedPayload, challenge);
1045 if (!payload) {
1046 return payload.message();
1047 }
1048
1049 return payload;
1050 }
1051
verifyCsr(const cppbor::Array & keysToSign,const std::vector<uint8_t> & csr,IRemotelyProvisionedComponent * provisionable,const std::vector<uint8_t> & challenge,bool isFactory)1052 ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyCsr(const cppbor::Array& keysToSign,
1053 const std::vector<uint8_t>& csr,
1054 IRemotelyProvisionedComponent* provisionable,
1055 const std::vector<uint8_t>& challenge,
1056 bool isFactory) {
1057 RpcHardwareInfo info;
1058 provisionable->getHardwareInfo(&info);
1059 if (info.versionNumber != 3) {
1060 return "Remotely provisioned component version (" + std::to_string(info.versionNumber) +
1061 ") does not match expected version (3).";
1062 }
1063
1064 auto csrPayload = parseAndValidateAuthenticatedRequest(csr, challenge);
1065 if (!csrPayload) {
1066 return csrPayload.message();
1067 }
1068
1069 return parseAndValidateCsrPayload(keysToSign, *csrPayload, provisionable, isFactory);
1070 }
1071
verifyFactoryCsr(const cppbor::Array & keysToSign,const std::vector<uint8_t> & csr,IRemotelyProvisionedComponent * provisionable,const std::vector<uint8_t> & challenge)1072 ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyFactoryCsr(
1073 const cppbor::Array& keysToSign, const std::vector<uint8_t>& csr,
1074 IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge) {
1075 return verifyCsr(keysToSign, csr, provisionable, challenge, /*isFactory=*/true);
1076 }
1077
verifyProductionCsr(const cppbor::Array & keysToSign,const std::vector<uint8_t> & csr,IRemotelyProvisionedComponent * provisionable,const std::vector<uint8_t> & challenge)1078 ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyProductionCsr(
1079 const cppbor::Array& keysToSign, const std::vector<uint8_t>& csr,
1080 IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge) {
1081 return verifyCsr(keysToSign, csr, provisionable, challenge, /*isFactory=*/false);
1082 }
1083
isCsrWithProperDiceChain(const std::vector<uint8_t> & csr)1084 ErrMsgOr<bool> isCsrWithProperDiceChain(const std::vector<uint8_t>& csr) {
1085 auto [parsedRequest, _, csrErrMsg] = cppbor::parse(csr);
1086 if (!parsedRequest) {
1087 return csrErrMsg;
1088 }
1089 if (!parsedRequest->asArray()) {
1090 return "AuthenticatedRequest is not a CBOR array.";
1091 }
1092 if (parsedRequest->asArray()->size() != 4U) {
1093 return "AuthenticatedRequest must contain version, UDS certificates, DICE chain, and "
1094 "signed data. However, the parsed AuthenticatedRequest has " +
1095 std::to_string(parsedRequest->asArray()->size()) + " entries.";
1096 }
1097
1098 auto version = parsedRequest->asArray()->get(0)->asUint();
1099 auto diceCertChain = parsedRequest->asArray()->get(2)->asArray();
1100
1101 if (!version || version->value() != 1U) {
1102 return "AuthenticatedRequest version must be an unsigned integer and must be equal to 1.";
1103 }
1104 if (!diceCertChain) {
1105 return "AuthenticatedRequest DiceCertChain must be an Array.";
1106 }
1107
1108 // DICE chain is [ pubkey, + DiceChainEntry ].
1109 auto diceChainKind = getDiceChainKind();
1110 if (!diceChainKind) {
1111 return diceChainKind.message();
1112 }
1113
1114 auto encodedDiceChain = diceCertChain->encode();
1115 auto chain = hwtrust::DiceChain::Verify(encodedDiceChain, *diceChainKind);
1116 if (!chain.ok()) return chain.error().message();
1117 return chain->IsProper();
1118 }
1119
1120 } // namespace aidl::android::hardware::security::keymint::remote_prov
1121