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