xref: /aosp_15_r20/hardware/interfaces/security/keymint/support/remote_prov_utils.cpp (revision 4d7e907c777eeecc4c5bd7cf640a754fac206ff7)
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