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