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