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