xref: /rk3399_rockchip-uboot/lib/avb/libavb_atx/avb_atx_validate.c (revision 871b2fe8ad298e6ca9157dfe5115092ae2b07b89)
137a7bc39SJason Zhu /*
237a7bc39SJason Zhu  * Copyright (C) 2016 The Android Open Source Project
337a7bc39SJason Zhu  *
437a7bc39SJason Zhu  * Permission is hereby granted, free of charge, to any person
537a7bc39SJason Zhu  * obtaining a copy of this software and associated documentation
637a7bc39SJason Zhu  * files (the "Software"), to deal in the Software without
737a7bc39SJason Zhu  * restriction, including without limitation the rights to use, copy,
837a7bc39SJason Zhu  * modify, merge, publish, distribute, sublicense, and/or sell copies
937a7bc39SJason Zhu  * of the Software, and to permit persons to whom the Software is
1037a7bc39SJason Zhu  * furnished to do so, subject to the following conditions:
1137a7bc39SJason Zhu  *
1237a7bc39SJason Zhu  * The above copyright notice and this permission notice shall be
1337a7bc39SJason Zhu  * included in all copies or substantial portions of the Software.
1437a7bc39SJason Zhu  *
1537a7bc39SJason Zhu  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1637a7bc39SJason Zhu  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1737a7bc39SJason Zhu  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
1837a7bc39SJason Zhu  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
1937a7bc39SJason Zhu  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
2037a7bc39SJason Zhu  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2137a7bc39SJason Zhu  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2237a7bc39SJason Zhu  * SOFTWARE.
2337a7bc39SJason Zhu  */
2437a7bc39SJason Zhu 
2537a7bc39SJason Zhu #include <android_avb/avb_atx_validate.h>
2637a7bc39SJason Zhu 
2737a7bc39SJason Zhu #include <android_avb/avb_rsa.h>
2837a7bc39SJason Zhu #include <android_avb/avb_sha.h>
2937a7bc39SJason Zhu #include <android_avb/avb_sysdeps.h>
3037a7bc39SJason Zhu #include <android_avb/avb_util.h>
3165f0143bSJason Zhu #include <android_avb/avb_ops_user.h>
3265f0143bSJason Zhu #include <android_avb/rk_avb_ops_user.h>
3365f0143bSJason Zhu #include <malloc.h>
3465f0143bSJason Zhu #include <common.h>
354a7c1780SJason Zhu #ifdef CONFIG_DM_CRYPTO
364a7c1780SJason Zhu #include <crypto.h>
3765f0143bSJason Zhu #endif
3837a7bc39SJason Zhu 
39ab608f80SJason Zhu /* The most recent unlock challenge generated. */
40ab608f80SJason Zhu static uint8_t last_unlock_challenge[AVB_ATX_UNLOCK_CHALLENGE_SIZE];
4169fdc596SJason Zhu static bool last_unlock_challenge_set = false;
42ab608f80SJason Zhu 
4337a7bc39SJason Zhu /* Computes the SHA256 |hash| of |length| bytes of |data|. */
sha256(const uint8_t * data,uint32_t length,uint8_t hash[AVB_SHA256_DIGEST_SIZE])4437a7bc39SJason Zhu static void sha256(const uint8_t* data,
4537a7bc39SJason Zhu                    uint32_t length,
4637a7bc39SJason Zhu                    uint8_t hash[AVB_SHA256_DIGEST_SIZE]) {
4737a7bc39SJason Zhu   AvbSHA256Ctx context;
485b0bc491SJoseph Chen 
495b0bc491SJoseph Chen   context.tot_len = length;
5037a7bc39SJason Zhu   avb_sha256_init(&context);
5137a7bc39SJason Zhu   avb_sha256_update(&context, data, length);
5237a7bc39SJason Zhu   uint8_t* tmp = avb_sha256_final(&context);
5337a7bc39SJason Zhu   avb_memcpy(hash, tmp, AVB_SHA256_DIGEST_SIZE);
5437a7bc39SJason Zhu }
5537a7bc39SJason Zhu 
5637a7bc39SJason Zhu /* Computes the SHA512 |hash| of |length| bytes of |data|. */
sha512(const uint8_t * data,uint32_t length,uint8_t hash[AVB_SHA512_DIGEST_SIZE])5737a7bc39SJason Zhu static void sha512(const uint8_t* data,
5837a7bc39SJason Zhu                    uint32_t length,
5937a7bc39SJason Zhu                    uint8_t hash[AVB_SHA512_DIGEST_SIZE]) {
6037a7bc39SJason Zhu   AvbSHA512Ctx context;
61*871b2fe8SJoseph Chen 
62*871b2fe8SJoseph Chen   context.tot_len = length;
6337a7bc39SJason Zhu   avb_sha512_init(&context);
6437a7bc39SJason Zhu   avb_sha512_update(&context, data, length);
6537a7bc39SJason Zhu   uint8_t* tmp = avb_sha512_final(&context);
6637a7bc39SJason Zhu   avb_memcpy(hash, tmp, AVB_SHA512_DIGEST_SIZE);
6737a7bc39SJason Zhu }
6837a7bc39SJason Zhu 
6937a7bc39SJason Zhu /* Computes the SHA256 |hash| of a NUL-terminated |str|. */
sha256_str(const char * str,uint8_t hash[AVB_SHA256_DIGEST_SIZE])7037a7bc39SJason Zhu static void sha256_str(const char* str, uint8_t hash[AVB_SHA256_DIGEST_SIZE]) {
7137a7bc39SJason Zhu   sha256((const uint8_t*)str, avb_strlen(str), hash);
7237a7bc39SJason Zhu }
7337a7bc39SJason Zhu 
7437a7bc39SJason Zhu /* Verifies structure and |expected_hash| of permanent |attributes|. */
verify_permanent_attributes(const AvbAtxPermanentAttributes * attributes,const uint8_t expected_hash[AVB_SHA256_DIGEST_SIZE])7537a7bc39SJason Zhu static bool verify_permanent_attributes(
7637a7bc39SJason Zhu     const AvbAtxPermanentAttributes* attributes,
77ab608f80SJason Zhu     const uint8_t expected_hash[AVB_SHA256_DIGEST_SIZE]) {
7837a7bc39SJason Zhu   uint8_t hash[AVB_SHA256_DIGEST_SIZE];
7974b485fbSJason Zhu #ifdef CONFIG_ROCKCHIP_PRELOADER_PUB_KEY
804a7c1780SJason Zhu #ifdef CONFIG_DM_CRYPTO
814a7c1780SJason Zhu   u32 cap = CRYPTO_MD5 | CRYPTO_SHA1 | CRYPTO_SHA256 | CRYPTO_RSA2048;
8265f0143bSJason Zhu   uint8_t rsa_hash[256] = {0};
8365f0143bSJason Zhu   uint8_t rsa_hash_revert[256] = {0};
8465f0143bSJason Zhu   unsigned int rsaResult_temp[8];
8565f0143bSJason Zhu   unsigned char rsaResult[32] = {0};
864a7c1780SJason Zhu   struct rk_pub_key pub_key;
874a7c1780SJason Zhu   struct udevice *dev;
884a7c1780SJason Zhu   rsa_key rsa_key;
8965f0143bSJason Zhu   char *temp;
9065f0143bSJason Zhu   int ret = 0;
914a7c1780SJason Zhu   int i;
9265f0143bSJason Zhu 
9365f0143bSJason Zhu   memset(&pub_key, 0, sizeof(struct rk_pub_key));
9465f0143bSJason Zhu   ret = rk_avb_get_pub_key(&pub_key);
9565f0143bSJason Zhu   if (ret)
9665f0143bSJason Zhu     return false;
9765f0143bSJason Zhu 
9865f0143bSJason Zhu   ret = rk_avb_get_perm_attr_cer(rsa_hash, 256);
9965f0143bSJason Zhu   if (ret) {
10065f0143bSJason Zhu     avb_error("get_perm_attr_cer error\n");
10165f0143bSJason Zhu     return false;
10265f0143bSJason Zhu   }
10365f0143bSJason Zhu 
10465f0143bSJason Zhu   for (i = 0; i < 256; i++)
10565f0143bSJason Zhu     rsa_hash_revert[255-i] = rsa_hash[i];
10665f0143bSJason Zhu 
1074a7c1780SJason Zhu   dev = crypto_get_device(cap);
1084a7c1780SJason Zhu   if (!dev) {
1094a7c1780SJason Zhu     avb_error("Can't find crypto device for expected capability\n");
11065f0143bSJason Zhu     return false;
11165f0143bSJason Zhu   }
11265f0143bSJason Zhu 
1134a7c1780SJason Zhu   memset(&rsa_key, 0x00, sizeof(rsa_key));
1144a7c1780SJason Zhu   rsa_key.algo = CRYPTO_RSA2048;
1154a7c1780SJason Zhu   rsa_key.n = (u32 *)&pub_key.rsa_n;
1164a7c1780SJason Zhu   rsa_key.e = (u32 *)&pub_key.rsa_e;
11763a580aeSJason Zhu #ifdef CONFIG_ROCKCHIP_CRYPTO_V1
1184a7c1780SJason Zhu   rsa_key.c = (u32 *)&pub_key.rsa_c;
11963a580aeSJason Zhu #endif
1204a7c1780SJason Zhu   ret = crypto_rsa_verify(dev, &rsa_key, (u8 *)rsa_hash_revert, (u8 *)rsaResult_temp);
12165f0143bSJason Zhu   if (ret) {
1224a7c1780SJason Zhu     avb_error("Hardware verify error!\n");
12365f0143bSJason Zhu     return false;
12465f0143bSJason Zhu   }
12565f0143bSJason Zhu 
12665f0143bSJason Zhu   temp = (char *)rsaResult_temp;
12765f0143bSJason Zhu   for (i = 0; i < 32; i++)
12865f0143bSJason Zhu     rsaResult[31-i] = temp[i];
12965f0143bSJason Zhu 
13065f0143bSJason Zhu   sha256((const uint8_t*)attributes, sizeof(AvbAtxPermanentAttributes), hash);
13165f0143bSJason Zhu   if (memcmp((void*)rsaResult, (void*)hash, 32) == 0)
13265f0143bSJason Zhu     return true;
13365f0143bSJason Zhu 
13465f0143bSJason Zhu   return false;
13565f0143bSJason Zhu #endif
13665f0143bSJason Zhu #else
13737a7bc39SJason Zhu   if (attributes->version != 1) {
13837a7bc39SJason Zhu     avb_error("Unsupported permanent attributes version.\n");
13937a7bc39SJason Zhu     return false;
14037a7bc39SJason Zhu   }
14137a7bc39SJason Zhu   sha256((const uint8_t*)attributes, sizeof(AvbAtxPermanentAttributes), hash);
14237a7bc39SJason Zhu   if (0 != avb_safe_memcmp(hash, expected_hash, AVB_SHA256_DIGEST_SIZE)) {
14337a7bc39SJason Zhu     avb_error("Invalid permanent attributes.\n");
14437a7bc39SJason Zhu     return false;
14537a7bc39SJason Zhu   }
14637a7bc39SJason Zhu   return true;
14765f0143bSJason Zhu #endif
14837a7bc39SJason Zhu }
14937a7bc39SJason Zhu 
15037a7bc39SJason Zhu /* Verifies the format, key version, usage, and signature of a certificate. */
verify_certificate(const AvbAtxCertificate * certificate,const uint8_t authority[AVB_ATX_PUBLIC_KEY_SIZE],uint64_t minimum_key_version,const uint8_t expected_usage[AVB_SHA256_DIGEST_SIZE])151ab608f80SJason Zhu static bool verify_certificate(
152ab608f80SJason Zhu     const AvbAtxCertificate* certificate,
153ab608f80SJason Zhu     const uint8_t authority[AVB_ATX_PUBLIC_KEY_SIZE],
15437a7bc39SJason Zhu     uint64_t minimum_key_version,
155ab608f80SJason Zhu     const uint8_t expected_usage[AVB_SHA256_DIGEST_SIZE]) {
15637a7bc39SJason Zhu   const AvbAlgorithmData* algorithm_data;
15737a7bc39SJason Zhu   uint8_t certificate_hash[AVB_SHA512_DIGEST_SIZE];
15837a7bc39SJason Zhu 
15937a7bc39SJason Zhu   if (certificate->signed_data.version != 1) {
16037a7bc39SJason Zhu     avb_error("Unsupported certificate format.\n");
16137a7bc39SJason Zhu     return false;
16237a7bc39SJason Zhu   }
16337a7bc39SJason Zhu   algorithm_data = avb_get_algorithm_data(AVB_ALGORITHM_TYPE_SHA512_RSA4096);
16437a7bc39SJason Zhu   sha512((const uint8_t*)&certificate->signed_data,
16537a7bc39SJason Zhu          sizeof(AvbAtxCertificateSignedData),
16637a7bc39SJason Zhu          certificate_hash);
16737a7bc39SJason Zhu   if (!avb_rsa_verify(authority,
16837a7bc39SJason Zhu                       AVB_ATX_PUBLIC_KEY_SIZE,
16937a7bc39SJason Zhu                       certificate->signature,
17037a7bc39SJason Zhu                       AVB_RSA4096_NUM_BYTES,
17137a7bc39SJason Zhu                       certificate_hash,
17237a7bc39SJason Zhu                       AVB_SHA512_DIGEST_SIZE,
17337a7bc39SJason Zhu                       algorithm_data->padding,
17437a7bc39SJason Zhu                       algorithm_data->padding_len)) {
17537a7bc39SJason Zhu     avb_error("Invalid certificate signature.\n");
17637a7bc39SJason Zhu     return false;
17737a7bc39SJason Zhu   }
17837a7bc39SJason Zhu   if (certificate->signed_data.key_version < minimum_key_version) {
17937a7bc39SJason Zhu     avb_error("Key rollback detected.\n");
18037a7bc39SJason Zhu     return false;
18137a7bc39SJason Zhu   }
18237a7bc39SJason Zhu   if (0 != avb_safe_memcmp(certificate->signed_data.usage,
18337a7bc39SJason Zhu                            expected_usage,
18437a7bc39SJason Zhu                            AVB_SHA256_DIGEST_SIZE)) {
18537a7bc39SJason Zhu     avb_error("Invalid certificate usage.\n");
18637a7bc39SJason Zhu     return false;
18737a7bc39SJason Zhu   }
18837a7bc39SJason Zhu   return true;
18937a7bc39SJason Zhu }
19037a7bc39SJason Zhu 
19137a7bc39SJason Zhu /* Verifies signature and fields of a PIK certificate. */
verify_pik_certificate(const AvbAtxCertificate * certificate,const uint8_t authority[AVB_ATX_PUBLIC_KEY_SIZE],uint64_t minimum_version)192ab608f80SJason Zhu static bool verify_pik_certificate(
193ab608f80SJason Zhu     const AvbAtxCertificate* certificate,
194ab608f80SJason Zhu     const uint8_t authority[AVB_ATX_PUBLIC_KEY_SIZE],
19537a7bc39SJason Zhu     uint64_t minimum_version) {
19637a7bc39SJason Zhu   uint8_t expected_usage[AVB_SHA256_DIGEST_SIZE];
19737a7bc39SJason Zhu 
19837a7bc39SJason Zhu   sha256_str("com.google.android.things.vboot.ca", expected_usage);
19937a7bc39SJason Zhu   if (!verify_certificate(
20037a7bc39SJason Zhu           certificate, authority, minimum_version, expected_usage)) {
20137a7bc39SJason Zhu     avb_error("Invalid PIK certificate.\n");
20237a7bc39SJason Zhu     return false;
20337a7bc39SJason Zhu   }
20437a7bc39SJason Zhu   return true;
20537a7bc39SJason Zhu }
20637a7bc39SJason Zhu 
20737a7bc39SJason Zhu /* Verifies signature and fields of a PSK certificate. */
verify_psk_certificate(const AvbAtxCertificate * certificate,const uint8_t authority[AVB_ATX_PUBLIC_KEY_SIZE],uint64_t minimum_version,const uint8_t product_id[AVB_ATX_PRODUCT_ID_SIZE])20837a7bc39SJason Zhu static bool verify_psk_certificate(
209ab608f80SJason Zhu     const AvbAtxCertificate* certificate,
210ab608f80SJason Zhu     const uint8_t authority[AVB_ATX_PUBLIC_KEY_SIZE],
21137a7bc39SJason Zhu     uint64_t minimum_version,
212ab608f80SJason Zhu     const uint8_t product_id[AVB_ATX_PRODUCT_ID_SIZE]) {
21337a7bc39SJason Zhu   uint8_t expected_subject[AVB_SHA256_DIGEST_SIZE];
21437a7bc39SJason Zhu   uint8_t expected_usage[AVB_SHA256_DIGEST_SIZE];
21537a7bc39SJason Zhu 
21637a7bc39SJason Zhu   sha256_str("com.google.android.things.vboot", expected_usage);
21737a7bc39SJason Zhu   if (!verify_certificate(
21837a7bc39SJason Zhu           certificate, authority, minimum_version, expected_usage)) {
21937a7bc39SJason Zhu     avb_error("Invalid PSK certificate.\n");
22037a7bc39SJason Zhu     return false;
22137a7bc39SJason Zhu   }
22237a7bc39SJason Zhu   sha256(product_id, AVB_ATX_PRODUCT_ID_SIZE, expected_subject);
22337a7bc39SJason Zhu   if (0 != avb_safe_memcmp(certificate->signed_data.subject,
22437a7bc39SJason Zhu                            expected_subject,
22537a7bc39SJason Zhu                            AVB_SHA256_DIGEST_SIZE)) {
226ab608f80SJason Zhu     avb_error("PSK: Product ID mismatch.\n");
227ab608f80SJason Zhu     return false;
228ab608f80SJason Zhu   }
229ab608f80SJason Zhu   return true;
230ab608f80SJason Zhu }
231ab608f80SJason Zhu 
232ab608f80SJason Zhu /* Verifies signature and fields of a PUK certificate. */
verify_puk_certificate(const AvbAtxCertificate * certificate,const uint8_t authority[AVB_ATX_PUBLIC_KEY_SIZE],uint64_t minimum_version,const uint8_t product_id[AVB_ATX_PRODUCT_ID_SIZE])233ab608f80SJason Zhu static bool verify_puk_certificate(
234ab608f80SJason Zhu     const AvbAtxCertificate* certificate,
235ab608f80SJason Zhu     const uint8_t authority[AVB_ATX_PUBLIC_KEY_SIZE],
236ab608f80SJason Zhu     uint64_t minimum_version,
237ab608f80SJason Zhu     const uint8_t product_id[AVB_ATX_PRODUCT_ID_SIZE]) {
238ab608f80SJason Zhu   uint8_t expected_subject[AVB_SHA256_DIGEST_SIZE];
239ab608f80SJason Zhu   uint8_t expected_usage[AVB_SHA256_DIGEST_SIZE];
240ab608f80SJason Zhu 
241ab608f80SJason Zhu   sha256_str("com.google.android.things.vboot.unlock", expected_usage);
242ab608f80SJason Zhu   if (!verify_certificate(
243ab608f80SJason Zhu           certificate, authority, minimum_version, expected_usage)) {
244ab608f80SJason Zhu     avb_error("Invalid PUK certificate.\n");
245ab608f80SJason Zhu     return false;
246ab608f80SJason Zhu   }
247ab608f80SJason Zhu   sha256(product_id, AVB_ATX_PRODUCT_ID_SIZE, expected_subject);
248ab608f80SJason Zhu   if (0 != avb_safe_memcmp(certificate->signed_data.subject,
249ab608f80SJason Zhu                            expected_subject,
250ab608f80SJason Zhu                            AVB_SHA256_DIGEST_SIZE)) {
251ab608f80SJason Zhu     avb_error("PUK: Product ID mismatch.\n");
25237a7bc39SJason Zhu     return false;
25337a7bc39SJason Zhu   }
25437a7bc39SJason Zhu   return true;
25537a7bc39SJason Zhu }
25637a7bc39SJason Zhu 
avb_atx_validate_vbmeta_public_key(AvbOps * ops,const uint8_t * public_key_data,size_t public_key_length,const uint8_t * public_key_metadata,size_t public_key_metadata_length,bool * out_is_trusted)25737a7bc39SJason Zhu AvbIOResult avb_atx_validate_vbmeta_public_key(
25837a7bc39SJason Zhu     AvbOps* ops,
25937a7bc39SJason Zhu     const uint8_t* public_key_data,
26037a7bc39SJason Zhu     size_t public_key_length,
26137a7bc39SJason Zhu     const uint8_t* public_key_metadata,
26237a7bc39SJason Zhu     size_t public_key_metadata_length,
26337a7bc39SJason Zhu     bool* out_is_trusted) {
26437a7bc39SJason Zhu   AvbIOResult result = AVB_IO_RESULT_OK;
26537a7bc39SJason Zhu   AvbAtxPermanentAttributes permanent_attributes;
26637a7bc39SJason Zhu   uint8_t permanent_attributes_hash[AVB_SHA256_DIGEST_SIZE];
26737a7bc39SJason Zhu   AvbAtxPublicKeyMetadata metadata;
26837a7bc39SJason Zhu   uint64_t minimum_version;
26937a7bc39SJason Zhu 
27037a7bc39SJason Zhu   /* Be pessimistic so we can exit early without having to remember to clear.
27137a7bc39SJason Zhu    */
27237a7bc39SJason Zhu   *out_is_trusted = false;
27337a7bc39SJason Zhu 
27437a7bc39SJason Zhu   /* Read and verify permanent attributes. */
27537a7bc39SJason Zhu   result = ops->atx_ops->read_permanent_attributes(ops->atx_ops,
27637a7bc39SJason Zhu                                                    &permanent_attributes);
27737a7bc39SJason Zhu   if (result != AVB_IO_RESULT_OK) {
27837a7bc39SJason Zhu     avb_error("Failed to read permanent attributes.\n");
27937a7bc39SJason Zhu     return result;
28037a7bc39SJason Zhu   }
28137a7bc39SJason Zhu   result = ops->atx_ops->read_permanent_attributes_hash(
28237a7bc39SJason Zhu       ops->atx_ops, permanent_attributes_hash);
28337a7bc39SJason Zhu   if (result != AVB_IO_RESULT_OK) {
28437a7bc39SJason Zhu     avb_error("Failed to read permanent attributes hash.\n");
28537a7bc39SJason Zhu     return result;
28637a7bc39SJason Zhu   }
28737a7bc39SJason Zhu   if (!verify_permanent_attributes(&permanent_attributes,
28837a7bc39SJason Zhu                                    permanent_attributes_hash)) {
28937a7bc39SJason Zhu     return AVB_IO_RESULT_OK;
29037a7bc39SJason Zhu   }
29137a7bc39SJason Zhu 
29237a7bc39SJason Zhu   /* Sanity check public key metadata. */
29337a7bc39SJason Zhu   if (public_key_metadata_length != sizeof(AvbAtxPublicKeyMetadata)) {
29437a7bc39SJason Zhu     avb_error("Invalid public key metadata.\n");
29537a7bc39SJason Zhu     return AVB_IO_RESULT_OK;
29637a7bc39SJason Zhu   }
29737a7bc39SJason Zhu   avb_memcpy(&metadata, public_key_metadata, sizeof(AvbAtxPublicKeyMetadata));
29837a7bc39SJason Zhu   if (metadata.version != 1) {
29937a7bc39SJason Zhu     avb_error("Unsupported public key metadata.\n");
30037a7bc39SJason Zhu     return AVB_IO_RESULT_OK;
30137a7bc39SJason Zhu   }
30237a7bc39SJason Zhu 
30337a7bc39SJason Zhu   /* Verify the PIK certificate. */
30437a7bc39SJason Zhu   result = ops->read_rollback_index(
30537a7bc39SJason Zhu       ops, AVB_ATX_PIK_VERSION_LOCATION, &minimum_version);
30637a7bc39SJason Zhu   if (result != AVB_IO_RESULT_OK) {
30737a7bc39SJason Zhu     avb_error("Failed to read PIK minimum version.\n");
30837a7bc39SJason Zhu     return result;
30937a7bc39SJason Zhu   }
31037a7bc39SJason Zhu   if (!verify_pik_certificate(&metadata.product_intermediate_key_certificate,
31137a7bc39SJason Zhu                               permanent_attributes.product_root_public_key,
31237a7bc39SJason Zhu                               minimum_version)) {
31337a7bc39SJason Zhu     return AVB_IO_RESULT_OK;
31437a7bc39SJason Zhu   }
31537a7bc39SJason Zhu 
31637a7bc39SJason Zhu   /* Verify the PSK certificate. */
31737a7bc39SJason Zhu   result = ops->read_rollback_index(
31837a7bc39SJason Zhu       ops, AVB_ATX_PSK_VERSION_LOCATION, &minimum_version);
31937a7bc39SJason Zhu   if (result != AVB_IO_RESULT_OK) {
32037a7bc39SJason Zhu     avb_error("Failed to read PSK minimum version.\n");
32137a7bc39SJason Zhu     return result;
32237a7bc39SJason Zhu   }
32337a7bc39SJason Zhu   if (!verify_psk_certificate(
32437a7bc39SJason Zhu           &metadata.product_signing_key_certificate,
32537a7bc39SJason Zhu           metadata.product_intermediate_key_certificate.signed_data.public_key,
32637a7bc39SJason Zhu           minimum_version,
32737a7bc39SJason Zhu           permanent_attributes.product_id)) {
32837a7bc39SJason Zhu     return AVB_IO_RESULT_OK;
32937a7bc39SJason Zhu   }
33037a7bc39SJason Zhu 
33137a7bc39SJason Zhu   /* Verify the PSK is the same key that verified vbmeta. */
33237a7bc39SJason Zhu   if (public_key_length != AVB_ATX_PUBLIC_KEY_SIZE) {
33337a7bc39SJason Zhu     avb_error("Public key length mismatch.\n");
33437a7bc39SJason Zhu     return AVB_IO_RESULT_OK;
33537a7bc39SJason Zhu   }
33637a7bc39SJason Zhu   if (0 != avb_safe_memcmp(
33737a7bc39SJason Zhu                metadata.product_signing_key_certificate.signed_data.public_key,
33837a7bc39SJason Zhu                public_key_data,
33937a7bc39SJason Zhu                AVB_ATX_PUBLIC_KEY_SIZE)) {
34037a7bc39SJason Zhu     avb_error("Public key mismatch.\n");
34137a7bc39SJason Zhu     return AVB_IO_RESULT_OK;
34237a7bc39SJason Zhu   }
34337a7bc39SJason Zhu 
34437a7bc39SJason Zhu   /* Report the key versions used during verification. */
34537a7bc39SJason Zhu   ops->atx_ops->set_key_version(
34637a7bc39SJason Zhu       ops->atx_ops,
34737a7bc39SJason Zhu       AVB_ATX_PIK_VERSION_LOCATION,
34837a7bc39SJason Zhu       metadata.product_intermediate_key_certificate.signed_data.key_version);
34937a7bc39SJason Zhu   ops->atx_ops->set_key_version(
35037a7bc39SJason Zhu       ops->atx_ops,
35137a7bc39SJason Zhu       AVB_ATX_PSK_VERSION_LOCATION,
35237a7bc39SJason Zhu       metadata.product_signing_key_certificate.signed_data.key_version);
35337a7bc39SJason Zhu 
35437a7bc39SJason Zhu   *out_is_trusted = true;
35537a7bc39SJason Zhu   return AVB_IO_RESULT_OK;
35637a7bc39SJason Zhu }
357ab608f80SJason Zhu 
avb_atx_generate_unlock_challenge(AvbAtxOps * atx_ops,AvbAtxUnlockChallenge * out_unlock_challenge)358ab608f80SJason Zhu AvbIOResult avb_atx_generate_unlock_challenge(
359ab608f80SJason Zhu     AvbAtxOps* atx_ops, AvbAtxUnlockChallenge* out_unlock_challenge) {
360ab608f80SJason Zhu   AvbIOResult result = AVB_IO_RESULT_OK;
361ab608f80SJason Zhu   AvbAtxPermanentAttributes permanent_attributes;
362ab608f80SJason Zhu 
363ab608f80SJason Zhu   /* We need the permanent attributes to compute the product_id_hash. */
364ab608f80SJason Zhu   result = atx_ops->read_permanent_attributes(atx_ops, &permanent_attributes);
365ab608f80SJason Zhu   if (result != AVB_IO_RESULT_OK) {
366ab608f80SJason Zhu     avb_error("Failed to read permanent attributes.\n");
367ab608f80SJason Zhu     return result;
368ab608f80SJason Zhu   }
369ab608f80SJason Zhu   result = atx_ops->get_random(
370ab608f80SJason Zhu       atx_ops, AVB_ATX_UNLOCK_CHALLENGE_SIZE, last_unlock_challenge);
371ab608f80SJason Zhu   if (result != AVB_IO_RESULT_OK) {
372ab608f80SJason Zhu     avb_error("Failed to generate random challenge.\n");
373ab608f80SJason Zhu     return result;
374ab608f80SJason Zhu   }
37569fdc596SJason Zhu   last_unlock_challenge_set = true;
376ab608f80SJason Zhu   out_unlock_challenge->version = 1;
377ab608f80SJason Zhu   sha256(permanent_attributes.product_id,
378ab608f80SJason Zhu          AVB_ATX_PRODUCT_ID_SIZE,
379ab608f80SJason Zhu          out_unlock_challenge->product_id_hash);
380ab608f80SJason Zhu   avb_memcpy(out_unlock_challenge->challenge,
381ab608f80SJason Zhu              last_unlock_challenge,
382ab608f80SJason Zhu              AVB_ATX_UNLOCK_CHALLENGE_SIZE);
383ab608f80SJason Zhu   return result;
384ab608f80SJason Zhu }
385ab608f80SJason Zhu 
avb_atx_validate_unlock_credential(AvbAtxOps * atx_ops,const AvbAtxUnlockCredential * unlock_credential,bool * out_is_trusted)386ab608f80SJason Zhu AvbIOResult avb_atx_validate_unlock_credential(
387ab608f80SJason Zhu     AvbAtxOps* atx_ops,
388ab608f80SJason Zhu     const AvbAtxUnlockCredential* unlock_credential,
389ab608f80SJason Zhu     bool* out_is_trusted) {
390ab608f80SJason Zhu   AvbIOResult result = AVB_IO_RESULT_OK;
391ab608f80SJason Zhu   AvbAtxPermanentAttributes permanent_attributes;
392ab608f80SJason Zhu   uint8_t permanent_attributes_hash[AVB_SHA256_DIGEST_SIZE];
393ab608f80SJason Zhu   uint64_t minimum_version;
394ab608f80SJason Zhu   const AvbAlgorithmData* algorithm_data;
395ab608f80SJason Zhu   uint8_t challenge_hash[AVB_SHA512_DIGEST_SIZE];
396ab608f80SJason Zhu 
397ab608f80SJason Zhu   /* Be pessimistic so we can exit early without having to remember to clear.
398ab608f80SJason Zhu    */
399ab608f80SJason Zhu   *out_is_trusted = false;
400ab608f80SJason Zhu 
401ab608f80SJason Zhu   /* Sanity check the credential. */
402ab608f80SJason Zhu   if (unlock_credential->version != 1) {
403ab608f80SJason Zhu     avb_error("Unsupported unlock credential format.\n");
404ab608f80SJason Zhu     return AVB_IO_RESULT_OK;
405ab608f80SJason Zhu   }
406ab608f80SJason Zhu 
407ab608f80SJason Zhu   /* Read and verify permanent attributes. */
408ab608f80SJason Zhu   result = atx_ops->read_permanent_attributes(atx_ops, &permanent_attributes);
409ab608f80SJason Zhu   if (result != AVB_IO_RESULT_OK) {
410ab608f80SJason Zhu     avb_error("Failed to read permanent attributes.\n");
411ab608f80SJason Zhu     return result;
412ab608f80SJason Zhu   }
413ab608f80SJason Zhu   result = atx_ops->read_permanent_attributes_hash(atx_ops,
414ab608f80SJason Zhu                                                    permanent_attributes_hash);
415ab608f80SJason Zhu   if (result != AVB_IO_RESULT_OK) {
416ab608f80SJason Zhu     avb_error("Failed to read permanent attributes hash.\n");
417ab608f80SJason Zhu     return result;
418ab608f80SJason Zhu   }
419ab608f80SJason Zhu   if (!verify_permanent_attributes(&permanent_attributes,
420ab608f80SJason Zhu                                    permanent_attributes_hash)) {
421ab608f80SJason Zhu     return AVB_IO_RESULT_OK;
422ab608f80SJason Zhu   }
423ab608f80SJason Zhu 
424ab608f80SJason Zhu   /* Verify the PIK certificate. */
425ab608f80SJason Zhu   result = atx_ops->ops->read_rollback_index(
426ab608f80SJason Zhu       atx_ops->ops, AVB_ATX_PIK_VERSION_LOCATION, &minimum_version);
427ab608f80SJason Zhu   if (result != AVB_IO_RESULT_OK) {
428ab608f80SJason Zhu     avb_error("Failed to read PIK minimum version.\n");
429ab608f80SJason Zhu     return result;
430ab608f80SJason Zhu   }
431ab608f80SJason Zhu   if (!verify_pik_certificate(
432ab608f80SJason Zhu           &unlock_credential->product_intermediate_key_certificate,
433ab608f80SJason Zhu           permanent_attributes.product_root_public_key,
434ab608f80SJason Zhu           minimum_version)) {
435ab608f80SJason Zhu     return AVB_IO_RESULT_OK;
436ab608f80SJason Zhu   }
437ab608f80SJason Zhu 
438ab608f80SJason Zhu   /* Verify the PUK certificate. The minimum version is shared with the PSK. */
439ab608f80SJason Zhu   result = atx_ops->ops->read_rollback_index(
440ab608f80SJason Zhu       atx_ops->ops, AVB_ATX_PSK_VERSION_LOCATION, &minimum_version);
441ab608f80SJason Zhu   if (result != AVB_IO_RESULT_OK) {
442ab608f80SJason Zhu     avb_error("Failed to read PSK minimum version.\n");
443ab608f80SJason Zhu     return result;
444ab608f80SJason Zhu   }
445ab608f80SJason Zhu   if (!verify_puk_certificate(
446ab608f80SJason Zhu           &unlock_credential->product_unlock_key_certificate,
447ab608f80SJason Zhu           unlock_credential->product_intermediate_key_certificate.signed_data
448ab608f80SJason Zhu               .public_key,
449ab608f80SJason Zhu           minimum_version,
450ab608f80SJason Zhu           permanent_attributes.product_id)) {
451ab608f80SJason Zhu     return AVB_IO_RESULT_OK;
452ab608f80SJason Zhu   }
453ab608f80SJason Zhu 
45469fdc596SJason Zhu   /* Hash the most recent unlock challenge. */
45569fdc596SJason Zhu   if (!last_unlock_challenge_set) {
45669fdc596SJason Zhu     avb_error("Challenge does not exist.\n");
45769fdc596SJason Zhu     return AVB_IO_RESULT_OK;
45869fdc596SJason Zhu   }
45969fdc596SJason Zhu   sha512(last_unlock_challenge, AVB_ATX_UNLOCK_CHALLENGE_SIZE, challenge_hash);
46069fdc596SJason Zhu   last_unlock_challenge_set = false;
46169fdc596SJason Zhu 
462ab608f80SJason Zhu   /* Verify the challenge signature. */
463ab608f80SJason Zhu   algorithm_data = avb_get_algorithm_data(AVB_ALGORITHM_TYPE_SHA512_RSA4096);
464ab608f80SJason Zhu   if (!avb_rsa_verify(unlock_credential->product_unlock_key_certificate
465ab608f80SJason Zhu                           .signed_data.public_key,
466ab608f80SJason Zhu                       AVB_ATX_PUBLIC_KEY_SIZE,
467ab608f80SJason Zhu                       unlock_credential->challenge_signature,
468ab608f80SJason Zhu                       AVB_RSA4096_NUM_BYTES,
469ab608f80SJason Zhu                       challenge_hash,
470ab608f80SJason Zhu                       AVB_SHA512_DIGEST_SIZE,
471ab608f80SJason Zhu                       algorithm_data->padding,
472ab608f80SJason Zhu                       algorithm_data->padding_len)) {
473ab608f80SJason Zhu     avb_error("Invalid unlock challenge signature.\n");
474ab608f80SJason Zhu     return AVB_IO_RESULT_OK;
475ab608f80SJason Zhu   }
476ab608f80SJason Zhu 
477ab608f80SJason Zhu   *out_is_trusted = true;
478ab608f80SJason Zhu   return AVB_IO_RESULT_OK;
479ab608f80SJason Zhu }
480