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|. */ 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; 48*5b0bc491SJoseph Chen 49*5b0bc491SJoseph 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|. */ 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; 6137a7bc39SJason Zhu avb_sha512_init(&context); 6237a7bc39SJason Zhu avb_sha512_update(&context, data, length); 6337a7bc39SJason Zhu uint8_t* tmp = avb_sha512_final(&context); 6437a7bc39SJason Zhu avb_memcpy(hash, tmp, AVB_SHA512_DIGEST_SIZE); 6537a7bc39SJason Zhu } 6637a7bc39SJason Zhu 6737a7bc39SJason Zhu /* Computes the SHA256 |hash| of a NUL-terminated |str|. */ 6837a7bc39SJason Zhu static void sha256_str(const char* str, uint8_t hash[AVB_SHA256_DIGEST_SIZE]) { 6937a7bc39SJason Zhu sha256((const uint8_t*)str, avb_strlen(str), hash); 7037a7bc39SJason Zhu } 7137a7bc39SJason Zhu 7237a7bc39SJason Zhu /* Verifies structure and |expected_hash| of permanent |attributes|. */ 7337a7bc39SJason Zhu static bool verify_permanent_attributes( 7437a7bc39SJason Zhu const AvbAtxPermanentAttributes* attributes, 75ab608f80SJason Zhu const uint8_t expected_hash[AVB_SHA256_DIGEST_SIZE]) { 7637a7bc39SJason Zhu uint8_t hash[AVB_SHA256_DIGEST_SIZE]; 7774b485fbSJason Zhu #ifdef CONFIG_ROCKCHIP_PRELOADER_PUB_KEY 784a7c1780SJason Zhu #ifdef CONFIG_DM_CRYPTO 794a7c1780SJason Zhu u32 cap = CRYPTO_MD5 | CRYPTO_SHA1 | CRYPTO_SHA256 | CRYPTO_RSA2048; 8065f0143bSJason Zhu uint8_t rsa_hash[256] = {0}; 8165f0143bSJason Zhu uint8_t rsa_hash_revert[256] = {0}; 8265f0143bSJason Zhu unsigned int rsaResult_temp[8]; 8365f0143bSJason Zhu unsigned char rsaResult[32] = {0}; 844a7c1780SJason Zhu struct rk_pub_key pub_key; 854a7c1780SJason Zhu struct udevice *dev; 864a7c1780SJason Zhu rsa_key rsa_key; 8765f0143bSJason Zhu char *temp; 8865f0143bSJason Zhu int ret = 0; 894a7c1780SJason Zhu int i; 9065f0143bSJason Zhu 9165f0143bSJason Zhu memset(&pub_key, 0, sizeof(struct rk_pub_key)); 9265f0143bSJason Zhu ret = rk_avb_get_pub_key(&pub_key); 9365f0143bSJason Zhu if (ret) 9465f0143bSJason Zhu return false; 9565f0143bSJason Zhu 9665f0143bSJason Zhu ret = rk_avb_get_perm_attr_cer(rsa_hash, 256); 9765f0143bSJason Zhu if (ret) { 9865f0143bSJason Zhu avb_error("get_perm_attr_cer error\n"); 9965f0143bSJason Zhu return false; 10065f0143bSJason Zhu } 10165f0143bSJason Zhu 10265f0143bSJason Zhu for (i = 0; i < 256; i++) 10365f0143bSJason Zhu rsa_hash_revert[255-i] = rsa_hash[i]; 10465f0143bSJason Zhu 1054a7c1780SJason Zhu dev = crypto_get_device(cap); 1064a7c1780SJason Zhu if (!dev) { 1074a7c1780SJason Zhu avb_error("Can't find crypto device for expected capability\n"); 10865f0143bSJason Zhu return false; 10965f0143bSJason Zhu } 11065f0143bSJason Zhu 1114a7c1780SJason Zhu memset(&rsa_key, 0x00, sizeof(rsa_key)); 1124a7c1780SJason Zhu rsa_key.algo = CRYPTO_RSA2048; 1134a7c1780SJason Zhu rsa_key.n = (u32 *)&pub_key.rsa_n; 1144a7c1780SJason Zhu rsa_key.e = (u32 *)&pub_key.rsa_e; 11563a580aeSJason Zhu #ifdef CONFIG_ROCKCHIP_CRYPTO_V1 1164a7c1780SJason Zhu rsa_key.c = (u32 *)&pub_key.rsa_c; 11763a580aeSJason Zhu #endif 1184a7c1780SJason Zhu ret = crypto_rsa_verify(dev, &rsa_key, (u8 *)rsa_hash_revert, (u8 *)rsaResult_temp); 11965f0143bSJason Zhu if (ret) { 1204a7c1780SJason Zhu avb_error("Hardware verify error!\n"); 12165f0143bSJason Zhu return false; 12265f0143bSJason Zhu } 12365f0143bSJason Zhu 12465f0143bSJason Zhu temp = (char *)rsaResult_temp; 12565f0143bSJason Zhu for (i = 0; i < 32; i++) 12665f0143bSJason Zhu rsaResult[31-i] = temp[i]; 12765f0143bSJason Zhu 12865f0143bSJason Zhu sha256((const uint8_t*)attributes, sizeof(AvbAtxPermanentAttributes), hash); 12965f0143bSJason Zhu if (memcmp((void*)rsaResult, (void*)hash, 32) == 0) 13065f0143bSJason Zhu return true; 13165f0143bSJason Zhu 13265f0143bSJason Zhu return false; 13365f0143bSJason Zhu #endif 13465f0143bSJason Zhu #else 13537a7bc39SJason Zhu if (attributes->version != 1) { 13637a7bc39SJason Zhu avb_error("Unsupported permanent attributes version.\n"); 13737a7bc39SJason Zhu return false; 13837a7bc39SJason Zhu } 13937a7bc39SJason Zhu sha256((const uint8_t*)attributes, sizeof(AvbAtxPermanentAttributes), hash); 14037a7bc39SJason Zhu if (0 != avb_safe_memcmp(hash, expected_hash, AVB_SHA256_DIGEST_SIZE)) { 14137a7bc39SJason Zhu avb_error("Invalid permanent attributes.\n"); 14237a7bc39SJason Zhu return false; 14337a7bc39SJason Zhu } 14437a7bc39SJason Zhu return true; 14565f0143bSJason Zhu #endif 14637a7bc39SJason Zhu } 14737a7bc39SJason Zhu 14837a7bc39SJason Zhu /* Verifies the format, key version, usage, and signature of a certificate. */ 149ab608f80SJason Zhu static bool verify_certificate( 150ab608f80SJason Zhu const AvbAtxCertificate* certificate, 151ab608f80SJason Zhu const uint8_t authority[AVB_ATX_PUBLIC_KEY_SIZE], 15237a7bc39SJason Zhu uint64_t minimum_key_version, 153ab608f80SJason Zhu const uint8_t expected_usage[AVB_SHA256_DIGEST_SIZE]) { 15437a7bc39SJason Zhu const AvbAlgorithmData* algorithm_data; 15537a7bc39SJason Zhu uint8_t certificate_hash[AVB_SHA512_DIGEST_SIZE]; 15637a7bc39SJason Zhu 15737a7bc39SJason Zhu if (certificate->signed_data.version != 1) { 15837a7bc39SJason Zhu avb_error("Unsupported certificate format.\n"); 15937a7bc39SJason Zhu return false; 16037a7bc39SJason Zhu } 16137a7bc39SJason Zhu algorithm_data = avb_get_algorithm_data(AVB_ALGORITHM_TYPE_SHA512_RSA4096); 16237a7bc39SJason Zhu sha512((const uint8_t*)&certificate->signed_data, 16337a7bc39SJason Zhu sizeof(AvbAtxCertificateSignedData), 16437a7bc39SJason Zhu certificate_hash); 16537a7bc39SJason Zhu if (!avb_rsa_verify(authority, 16637a7bc39SJason Zhu AVB_ATX_PUBLIC_KEY_SIZE, 16737a7bc39SJason Zhu certificate->signature, 16837a7bc39SJason Zhu AVB_RSA4096_NUM_BYTES, 16937a7bc39SJason Zhu certificate_hash, 17037a7bc39SJason Zhu AVB_SHA512_DIGEST_SIZE, 17137a7bc39SJason Zhu algorithm_data->padding, 17237a7bc39SJason Zhu algorithm_data->padding_len)) { 17337a7bc39SJason Zhu avb_error("Invalid certificate signature.\n"); 17437a7bc39SJason Zhu return false; 17537a7bc39SJason Zhu } 17637a7bc39SJason Zhu if (certificate->signed_data.key_version < minimum_key_version) { 17737a7bc39SJason Zhu avb_error("Key rollback detected.\n"); 17837a7bc39SJason Zhu return false; 17937a7bc39SJason Zhu } 18037a7bc39SJason Zhu if (0 != avb_safe_memcmp(certificate->signed_data.usage, 18137a7bc39SJason Zhu expected_usage, 18237a7bc39SJason Zhu AVB_SHA256_DIGEST_SIZE)) { 18337a7bc39SJason Zhu avb_error("Invalid certificate usage.\n"); 18437a7bc39SJason Zhu return false; 18537a7bc39SJason Zhu } 18637a7bc39SJason Zhu return true; 18737a7bc39SJason Zhu } 18837a7bc39SJason Zhu 18937a7bc39SJason Zhu /* Verifies signature and fields of a PIK certificate. */ 190ab608f80SJason Zhu static bool verify_pik_certificate( 191ab608f80SJason Zhu const AvbAtxCertificate* certificate, 192ab608f80SJason Zhu const uint8_t authority[AVB_ATX_PUBLIC_KEY_SIZE], 19337a7bc39SJason Zhu uint64_t minimum_version) { 19437a7bc39SJason Zhu uint8_t expected_usage[AVB_SHA256_DIGEST_SIZE]; 19537a7bc39SJason Zhu 19637a7bc39SJason Zhu sha256_str("com.google.android.things.vboot.ca", expected_usage); 19737a7bc39SJason Zhu if (!verify_certificate( 19837a7bc39SJason Zhu certificate, authority, minimum_version, expected_usage)) { 19937a7bc39SJason Zhu avb_error("Invalid PIK certificate.\n"); 20037a7bc39SJason Zhu return false; 20137a7bc39SJason Zhu } 20237a7bc39SJason Zhu return true; 20337a7bc39SJason Zhu } 20437a7bc39SJason Zhu 20537a7bc39SJason Zhu /* Verifies signature and fields of a PSK certificate. */ 20637a7bc39SJason Zhu static bool verify_psk_certificate( 207ab608f80SJason Zhu const AvbAtxCertificate* certificate, 208ab608f80SJason Zhu const uint8_t authority[AVB_ATX_PUBLIC_KEY_SIZE], 20937a7bc39SJason Zhu uint64_t minimum_version, 210ab608f80SJason Zhu const uint8_t product_id[AVB_ATX_PRODUCT_ID_SIZE]) { 21137a7bc39SJason Zhu uint8_t expected_subject[AVB_SHA256_DIGEST_SIZE]; 21237a7bc39SJason Zhu uint8_t expected_usage[AVB_SHA256_DIGEST_SIZE]; 21337a7bc39SJason Zhu 21437a7bc39SJason Zhu sha256_str("com.google.android.things.vboot", expected_usage); 21537a7bc39SJason Zhu if (!verify_certificate( 21637a7bc39SJason Zhu certificate, authority, minimum_version, expected_usage)) { 21737a7bc39SJason Zhu avb_error("Invalid PSK certificate.\n"); 21837a7bc39SJason Zhu return false; 21937a7bc39SJason Zhu } 22037a7bc39SJason Zhu sha256(product_id, AVB_ATX_PRODUCT_ID_SIZE, expected_subject); 22137a7bc39SJason Zhu if (0 != avb_safe_memcmp(certificate->signed_data.subject, 22237a7bc39SJason Zhu expected_subject, 22337a7bc39SJason Zhu AVB_SHA256_DIGEST_SIZE)) { 224ab608f80SJason Zhu avb_error("PSK: Product ID mismatch.\n"); 225ab608f80SJason Zhu return false; 226ab608f80SJason Zhu } 227ab608f80SJason Zhu return true; 228ab608f80SJason Zhu } 229ab608f80SJason Zhu 230ab608f80SJason Zhu /* Verifies signature and fields of a PUK certificate. */ 231ab608f80SJason Zhu static bool verify_puk_certificate( 232ab608f80SJason Zhu const AvbAtxCertificate* certificate, 233ab608f80SJason Zhu const uint8_t authority[AVB_ATX_PUBLIC_KEY_SIZE], 234ab608f80SJason Zhu uint64_t minimum_version, 235ab608f80SJason Zhu const uint8_t product_id[AVB_ATX_PRODUCT_ID_SIZE]) { 236ab608f80SJason Zhu uint8_t expected_subject[AVB_SHA256_DIGEST_SIZE]; 237ab608f80SJason Zhu uint8_t expected_usage[AVB_SHA256_DIGEST_SIZE]; 238ab608f80SJason Zhu 239ab608f80SJason Zhu sha256_str("com.google.android.things.vboot.unlock", expected_usage); 240ab608f80SJason Zhu if (!verify_certificate( 241ab608f80SJason Zhu certificate, authority, minimum_version, expected_usage)) { 242ab608f80SJason Zhu avb_error("Invalid PUK certificate.\n"); 243ab608f80SJason Zhu return false; 244ab608f80SJason Zhu } 245ab608f80SJason Zhu sha256(product_id, AVB_ATX_PRODUCT_ID_SIZE, expected_subject); 246ab608f80SJason Zhu if (0 != avb_safe_memcmp(certificate->signed_data.subject, 247ab608f80SJason Zhu expected_subject, 248ab608f80SJason Zhu AVB_SHA256_DIGEST_SIZE)) { 249ab608f80SJason Zhu avb_error("PUK: Product ID mismatch.\n"); 25037a7bc39SJason Zhu return false; 25137a7bc39SJason Zhu } 25237a7bc39SJason Zhu return true; 25337a7bc39SJason Zhu } 25437a7bc39SJason Zhu 25537a7bc39SJason Zhu AvbIOResult avb_atx_validate_vbmeta_public_key( 25637a7bc39SJason Zhu AvbOps* ops, 25737a7bc39SJason Zhu const uint8_t* public_key_data, 25837a7bc39SJason Zhu size_t public_key_length, 25937a7bc39SJason Zhu const uint8_t* public_key_metadata, 26037a7bc39SJason Zhu size_t public_key_metadata_length, 26137a7bc39SJason Zhu bool* out_is_trusted) { 26237a7bc39SJason Zhu AvbIOResult result = AVB_IO_RESULT_OK; 26337a7bc39SJason Zhu AvbAtxPermanentAttributes permanent_attributes; 26437a7bc39SJason Zhu uint8_t permanent_attributes_hash[AVB_SHA256_DIGEST_SIZE]; 26537a7bc39SJason Zhu AvbAtxPublicKeyMetadata metadata; 26637a7bc39SJason Zhu uint64_t minimum_version; 26737a7bc39SJason Zhu 26837a7bc39SJason Zhu /* Be pessimistic so we can exit early without having to remember to clear. 26937a7bc39SJason Zhu */ 27037a7bc39SJason Zhu *out_is_trusted = false; 27137a7bc39SJason Zhu 27237a7bc39SJason Zhu /* Read and verify permanent attributes. */ 27337a7bc39SJason Zhu result = ops->atx_ops->read_permanent_attributes(ops->atx_ops, 27437a7bc39SJason Zhu &permanent_attributes); 27537a7bc39SJason Zhu if (result != AVB_IO_RESULT_OK) { 27637a7bc39SJason Zhu avb_error("Failed to read permanent attributes.\n"); 27737a7bc39SJason Zhu return result; 27837a7bc39SJason Zhu } 27937a7bc39SJason Zhu result = ops->atx_ops->read_permanent_attributes_hash( 28037a7bc39SJason Zhu ops->atx_ops, permanent_attributes_hash); 28137a7bc39SJason Zhu if (result != AVB_IO_RESULT_OK) { 28237a7bc39SJason Zhu avb_error("Failed to read permanent attributes hash.\n"); 28337a7bc39SJason Zhu return result; 28437a7bc39SJason Zhu } 28537a7bc39SJason Zhu if (!verify_permanent_attributes(&permanent_attributes, 28637a7bc39SJason Zhu permanent_attributes_hash)) { 28737a7bc39SJason Zhu return AVB_IO_RESULT_OK; 28837a7bc39SJason Zhu } 28937a7bc39SJason Zhu 29037a7bc39SJason Zhu /* Sanity check public key metadata. */ 29137a7bc39SJason Zhu if (public_key_metadata_length != sizeof(AvbAtxPublicKeyMetadata)) { 29237a7bc39SJason Zhu avb_error("Invalid public key metadata.\n"); 29337a7bc39SJason Zhu return AVB_IO_RESULT_OK; 29437a7bc39SJason Zhu } 29537a7bc39SJason Zhu avb_memcpy(&metadata, public_key_metadata, sizeof(AvbAtxPublicKeyMetadata)); 29637a7bc39SJason Zhu if (metadata.version != 1) { 29737a7bc39SJason Zhu avb_error("Unsupported public key metadata.\n"); 29837a7bc39SJason Zhu return AVB_IO_RESULT_OK; 29937a7bc39SJason Zhu } 30037a7bc39SJason Zhu 30137a7bc39SJason Zhu /* Verify the PIK certificate. */ 30237a7bc39SJason Zhu result = ops->read_rollback_index( 30337a7bc39SJason Zhu ops, AVB_ATX_PIK_VERSION_LOCATION, &minimum_version); 30437a7bc39SJason Zhu if (result != AVB_IO_RESULT_OK) { 30537a7bc39SJason Zhu avb_error("Failed to read PIK minimum version.\n"); 30637a7bc39SJason Zhu return result; 30737a7bc39SJason Zhu } 30837a7bc39SJason Zhu if (!verify_pik_certificate(&metadata.product_intermediate_key_certificate, 30937a7bc39SJason Zhu permanent_attributes.product_root_public_key, 31037a7bc39SJason Zhu minimum_version)) { 31137a7bc39SJason Zhu return AVB_IO_RESULT_OK; 31237a7bc39SJason Zhu } 31337a7bc39SJason Zhu 31437a7bc39SJason Zhu /* Verify the PSK certificate. */ 31537a7bc39SJason Zhu result = ops->read_rollback_index( 31637a7bc39SJason Zhu ops, AVB_ATX_PSK_VERSION_LOCATION, &minimum_version); 31737a7bc39SJason Zhu if (result != AVB_IO_RESULT_OK) { 31837a7bc39SJason Zhu avb_error("Failed to read PSK minimum version.\n"); 31937a7bc39SJason Zhu return result; 32037a7bc39SJason Zhu } 32137a7bc39SJason Zhu if (!verify_psk_certificate( 32237a7bc39SJason Zhu &metadata.product_signing_key_certificate, 32337a7bc39SJason Zhu metadata.product_intermediate_key_certificate.signed_data.public_key, 32437a7bc39SJason Zhu minimum_version, 32537a7bc39SJason Zhu permanent_attributes.product_id)) { 32637a7bc39SJason Zhu return AVB_IO_RESULT_OK; 32737a7bc39SJason Zhu } 32837a7bc39SJason Zhu 32937a7bc39SJason Zhu /* Verify the PSK is the same key that verified vbmeta. */ 33037a7bc39SJason Zhu if (public_key_length != AVB_ATX_PUBLIC_KEY_SIZE) { 33137a7bc39SJason Zhu avb_error("Public key length mismatch.\n"); 33237a7bc39SJason Zhu return AVB_IO_RESULT_OK; 33337a7bc39SJason Zhu } 33437a7bc39SJason Zhu if (0 != avb_safe_memcmp( 33537a7bc39SJason Zhu metadata.product_signing_key_certificate.signed_data.public_key, 33637a7bc39SJason Zhu public_key_data, 33737a7bc39SJason Zhu AVB_ATX_PUBLIC_KEY_SIZE)) { 33837a7bc39SJason Zhu avb_error("Public key mismatch.\n"); 33937a7bc39SJason Zhu return AVB_IO_RESULT_OK; 34037a7bc39SJason Zhu } 34137a7bc39SJason Zhu 34237a7bc39SJason Zhu /* Report the key versions used during verification. */ 34337a7bc39SJason Zhu ops->atx_ops->set_key_version( 34437a7bc39SJason Zhu ops->atx_ops, 34537a7bc39SJason Zhu AVB_ATX_PIK_VERSION_LOCATION, 34637a7bc39SJason Zhu metadata.product_intermediate_key_certificate.signed_data.key_version); 34737a7bc39SJason Zhu ops->atx_ops->set_key_version( 34837a7bc39SJason Zhu ops->atx_ops, 34937a7bc39SJason Zhu AVB_ATX_PSK_VERSION_LOCATION, 35037a7bc39SJason Zhu metadata.product_signing_key_certificate.signed_data.key_version); 35137a7bc39SJason Zhu 35237a7bc39SJason Zhu *out_is_trusted = true; 35337a7bc39SJason Zhu return AVB_IO_RESULT_OK; 35437a7bc39SJason Zhu } 355ab608f80SJason Zhu 356ab608f80SJason Zhu AvbIOResult avb_atx_generate_unlock_challenge( 357ab608f80SJason Zhu AvbAtxOps* atx_ops, AvbAtxUnlockChallenge* out_unlock_challenge) { 358ab608f80SJason Zhu AvbIOResult result = AVB_IO_RESULT_OK; 359ab608f80SJason Zhu AvbAtxPermanentAttributes permanent_attributes; 360ab608f80SJason Zhu 361ab608f80SJason Zhu /* We need the permanent attributes to compute the product_id_hash. */ 362ab608f80SJason Zhu result = atx_ops->read_permanent_attributes(atx_ops, &permanent_attributes); 363ab608f80SJason Zhu if (result != AVB_IO_RESULT_OK) { 364ab608f80SJason Zhu avb_error("Failed to read permanent attributes.\n"); 365ab608f80SJason Zhu return result; 366ab608f80SJason Zhu } 367ab608f80SJason Zhu result = atx_ops->get_random( 368ab608f80SJason Zhu atx_ops, AVB_ATX_UNLOCK_CHALLENGE_SIZE, last_unlock_challenge); 369ab608f80SJason Zhu if (result != AVB_IO_RESULT_OK) { 370ab608f80SJason Zhu avb_error("Failed to generate random challenge.\n"); 371ab608f80SJason Zhu return result; 372ab608f80SJason Zhu } 37369fdc596SJason Zhu last_unlock_challenge_set = true; 374ab608f80SJason Zhu out_unlock_challenge->version = 1; 375ab608f80SJason Zhu sha256(permanent_attributes.product_id, 376ab608f80SJason Zhu AVB_ATX_PRODUCT_ID_SIZE, 377ab608f80SJason Zhu out_unlock_challenge->product_id_hash); 378ab608f80SJason Zhu avb_memcpy(out_unlock_challenge->challenge, 379ab608f80SJason Zhu last_unlock_challenge, 380ab608f80SJason Zhu AVB_ATX_UNLOCK_CHALLENGE_SIZE); 381ab608f80SJason Zhu return result; 382ab608f80SJason Zhu } 383ab608f80SJason Zhu 384ab608f80SJason Zhu AvbIOResult avb_atx_validate_unlock_credential( 385ab608f80SJason Zhu AvbAtxOps* atx_ops, 386ab608f80SJason Zhu const AvbAtxUnlockCredential* unlock_credential, 387ab608f80SJason Zhu bool* out_is_trusted) { 388ab608f80SJason Zhu AvbIOResult result = AVB_IO_RESULT_OK; 389ab608f80SJason Zhu AvbAtxPermanentAttributes permanent_attributes; 390ab608f80SJason Zhu uint8_t permanent_attributes_hash[AVB_SHA256_DIGEST_SIZE]; 391ab608f80SJason Zhu uint64_t minimum_version; 392ab608f80SJason Zhu const AvbAlgorithmData* algorithm_data; 393ab608f80SJason Zhu uint8_t challenge_hash[AVB_SHA512_DIGEST_SIZE]; 394ab608f80SJason Zhu 395ab608f80SJason Zhu /* Be pessimistic so we can exit early without having to remember to clear. 396ab608f80SJason Zhu */ 397ab608f80SJason Zhu *out_is_trusted = false; 398ab608f80SJason Zhu 399ab608f80SJason Zhu /* Sanity check the credential. */ 400ab608f80SJason Zhu if (unlock_credential->version != 1) { 401ab608f80SJason Zhu avb_error("Unsupported unlock credential format.\n"); 402ab608f80SJason Zhu return AVB_IO_RESULT_OK; 403ab608f80SJason Zhu } 404ab608f80SJason Zhu 405ab608f80SJason Zhu /* Read and verify permanent attributes. */ 406ab608f80SJason Zhu result = atx_ops->read_permanent_attributes(atx_ops, &permanent_attributes); 407ab608f80SJason Zhu if (result != AVB_IO_RESULT_OK) { 408ab608f80SJason Zhu avb_error("Failed to read permanent attributes.\n"); 409ab608f80SJason Zhu return result; 410ab608f80SJason Zhu } 411ab608f80SJason Zhu result = atx_ops->read_permanent_attributes_hash(atx_ops, 412ab608f80SJason Zhu permanent_attributes_hash); 413ab608f80SJason Zhu if (result != AVB_IO_RESULT_OK) { 414ab608f80SJason Zhu avb_error("Failed to read permanent attributes hash.\n"); 415ab608f80SJason Zhu return result; 416ab608f80SJason Zhu } 417ab608f80SJason Zhu if (!verify_permanent_attributes(&permanent_attributes, 418ab608f80SJason Zhu permanent_attributes_hash)) { 419ab608f80SJason Zhu return AVB_IO_RESULT_OK; 420ab608f80SJason Zhu } 421ab608f80SJason Zhu 422ab608f80SJason Zhu /* Verify the PIK certificate. */ 423ab608f80SJason Zhu result = atx_ops->ops->read_rollback_index( 424ab608f80SJason Zhu atx_ops->ops, AVB_ATX_PIK_VERSION_LOCATION, &minimum_version); 425ab608f80SJason Zhu if (result != AVB_IO_RESULT_OK) { 426ab608f80SJason Zhu avb_error("Failed to read PIK minimum version.\n"); 427ab608f80SJason Zhu return result; 428ab608f80SJason Zhu } 429ab608f80SJason Zhu if (!verify_pik_certificate( 430ab608f80SJason Zhu &unlock_credential->product_intermediate_key_certificate, 431ab608f80SJason Zhu permanent_attributes.product_root_public_key, 432ab608f80SJason Zhu minimum_version)) { 433ab608f80SJason Zhu return AVB_IO_RESULT_OK; 434ab608f80SJason Zhu } 435ab608f80SJason Zhu 436ab608f80SJason Zhu /* Verify the PUK certificate. The minimum version is shared with the PSK. */ 437ab608f80SJason Zhu result = atx_ops->ops->read_rollback_index( 438ab608f80SJason Zhu atx_ops->ops, AVB_ATX_PSK_VERSION_LOCATION, &minimum_version); 439ab608f80SJason Zhu if (result != AVB_IO_RESULT_OK) { 440ab608f80SJason Zhu avb_error("Failed to read PSK minimum version.\n"); 441ab608f80SJason Zhu return result; 442ab608f80SJason Zhu } 443ab608f80SJason Zhu if (!verify_puk_certificate( 444ab608f80SJason Zhu &unlock_credential->product_unlock_key_certificate, 445ab608f80SJason Zhu unlock_credential->product_intermediate_key_certificate.signed_data 446ab608f80SJason Zhu .public_key, 447ab608f80SJason Zhu minimum_version, 448ab608f80SJason Zhu permanent_attributes.product_id)) { 449ab608f80SJason Zhu return AVB_IO_RESULT_OK; 450ab608f80SJason Zhu } 451ab608f80SJason Zhu 45269fdc596SJason Zhu /* Hash the most recent unlock challenge. */ 45369fdc596SJason Zhu if (!last_unlock_challenge_set) { 45469fdc596SJason Zhu avb_error("Challenge does not exist.\n"); 45569fdc596SJason Zhu return AVB_IO_RESULT_OK; 45669fdc596SJason Zhu } 45769fdc596SJason Zhu sha512(last_unlock_challenge, AVB_ATX_UNLOCK_CHALLENGE_SIZE, challenge_hash); 45869fdc596SJason Zhu last_unlock_challenge_set = false; 45969fdc596SJason Zhu 460ab608f80SJason Zhu /* Verify the challenge signature. */ 461ab608f80SJason Zhu algorithm_data = avb_get_algorithm_data(AVB_ALGORITHM_TYPE_SHA512_RSA4096); 462ab608f80SJason Zhu if (!avb_rsa_verify(unlock_credential->product_unlock_key_certificate 463ab608f80SJason Zhu .signed_data.public_key, 464ab608f80SJason Zhu AVB_ATX_PUBLIC_KEY_SIZE, 465ab608f80SJason Zhu unlock_credential->challenge_signature, 466ab608f80SJason Zhu AVB_RSA4096_NUM_BYTES, 467ab608f80SJason Zhu challenge_hash, 468ab608f80SJason Zhu AVB_SHA512_DIGEST_SIZE, 469ab608f80SJason Zhu algorithm_data->padding, 470ab608f80SJason Zhu algorithm_data->padding_len)) { 471ab608f80SJason Zhu avb_error("Invalid unlock challenge signature.\n"); 472ab608f80SJason Zhu return AVB_IO_RESULT_OK; 473ab608f80SJason Zhu } 474ab608f80SJason Zhu 475ab608f80SJason Zhu *out_is_trusted = true; 476ab608f80SJason Zhu return AVB_IO_RESULT_OK; 477ab608f80SJason Zhu } 478