1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright (C) 2016 The Android Open Source Project
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Permission is hereby granted, free of charge, to any person
5*4882a593Smuzhiyun * obtaining a copy of this software and associated documentation
6*4882a593Smuzhiyun * files (the "Software"), to deal in the Software without
7*4882a593Smuzhiyun * restriction, including without limitation the rights to use, copy,
8*4882a593Smuzhiyun * modify, merge, publish, distribute, sublicense, and/or sell copies
9*4882a593Smuzhiyun * of the Software, and to permit persons to whom the Software is
10*4882a593Smuzhiyun * furnished to do so, subject to the following conditions:
11*4882a593Smuzhiyun *
12*4882a593Smuzhiyun * The above copyright notice and this permission notice shall be
13*4882a593Smuzhiyun * included in all copies or substantial portions of the Software.
14*4882a593Smuzhiyun *
15*4882a593Smuzhiyun * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16*4882a593Smuzhiyun * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17*4882a593Smuzhiyun * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18*4882a593Smuzhiyun * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19*4882a593Smuzhiyun * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20*4882a593Smuzhiyun * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21*4882a593Smuzhiyun * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22*4882a593Smuzhiyun * SOFTWARE.
23*4882a593Smuzhiyun */
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun #include <android_avb/avb_atx_validate.h>
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun #include <android_avb/avb_rsa.h>
28*4882a593Smuzhiyun #include <android_avb/avb_sha.h>
29*4882a593Smuzhiyun #include <android_avb/avb_sysdeps.h>
30*4882a593Smuzhiyun #include <android_avb/avb_util.h>
31*4882a593Smuzhiyun #include <android_avb/avb_ops_user.h>
32*4882a593Smuzhiyun #include <android_avb/rk_avb_ops_user.h>
33*4882a593Smuzhiyun #include <malloc.h>
34*4882a593Smuzhiyun #include <common.h>
35*4882a593Smuzhiyun #ifdef CONFIG_DM_CRYPTO
36*4882a593Smuzhiyun #include <crypto.h>
37*4882a593Smuzhiyun #endif
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun /* The most recent unlock challenge generated. */
40*4882a593Smuzhiyun static uint8_t last_unlock_challenge[AVB_ATX_UNLOCK_CHALLENGE_SIZE];
41*4882a593Smuzhiyun static bool last_unlock_challenge_set = false;
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun /* Computes the SHA256 |hash| of |length| bytes of |data|. */
sha256(const uint8_t * data,uint32_t length,uint8_t hash[AVB_SHA256_DIGEST_SIZE])44*4882a593Smuzhiyun static void sha256(const uint8_t* data,
45*4882a593Smuzhiyun uint32_t length,
46*4882a593Smuzhiyun uint8_t hash[AVB_SHA256_DIGEST_SIZE]) {
47*4882a593Smuzhiyun AvbSHA256Ctx context;
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun context.tot_len = length;
50*4882a593Smuzhiyun avb_sha256_init(&context);
51*4882a593Smuzhiyun avb_sha256_update(&context, data, length);
52*4882a593Smuzhiyun uint8_t* tmp = avb_sha256_final(&context);
53*4882a593Smuzhiyun avb_memcpy(hash, tmp, AVB_SHA256_DIGEST_SIZE);
54*4882a593Smuzhiyun }
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun /* Computes the SHA512 |hash| of |length| bytes of |data|. */
sha512(const uint8_t * data,uint32_t length,uint8_t hash[AVB_SHA512_DIGEST_SIZE])57*4882a593Smuzhiyun static void sha512(const uint8_t* data,
58*4882a593Smuzhiyun uint32_t length,
59*4882a593Smuzhiyun uint8_t hash[AVB_SHA512_DIGEST_SIZE]) {
60*4882a593Smuzhiyun AvbSHA512Ctx context;
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun context.tot_len = length;
63*4882a593Smuzhiyun avb_sha512_init(&context);
64*4882a593Smuzhiyun avb_sha512_update(&context, data, length);
65*4882a593Smuzhiyun uint8_t* tmp = avb_sha512_final(&context);
66*4882a593Smuzhiyun avb_memcpy(hash, tmp, AVB_SHA512_DIGEST_SIZE);
67*4882a593Smuzhiyun }
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun /* Computes the SHA256 |hash| of a NUL-terminated |str|. */
sha256_str(const char * str,uint8_t hash[AVB_SHA256_DIGEST_SIZE])70*4882a593Smuzhiyun static void sha256_str(const char* str, uint8_t hash[AVB_SHA256_DIGEST_SIZE]) {
71*4882a593Smuzhiyun sha256((const uint8_t*)str, avb_strlen(str), hash);
72*4882a593Smuzhiyun }
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun /* Verifies structure and |expected_hash| of permanent |attributes|. */
verify_permanent_attributes(const AvbAtxPermanentAttributes * attributes,const uint8_t expected_hash[AVB_SHA256_DIGEST_SIZE])75*4882a593Smuzhiyun static bool verify_permanent_attributes(
76*4882a593Smuzhiyun const AvbAtxPermanentAttributes* attributes,
77*4882a593Smuzhiyun const uint8_t expected_hash[AVB_SHA256_DIGEST_SIZE]) {
78*4882a593Smuzhiyun uint8_t hash[AVB_SHA256_DIGEST_SIZE];
79*4882a593Smuzhiyun #ifdef CONFIG_ROCKCHIP_PRELOADER_PUB_KEY
80*4882a593Smuzhiyun #ifdef CONFIG_DM_CRYPTO
81*4882a593Smuzhiyun u32 cap = CRYPTO_MD5 | CRYPTO_SHA1 | CRYPTO_SHA256 | CRYPTO_RSA2048;
82*4882a593Smuzhiyun uint8_t rsa_hash[256] = {0};
83*4882a593Smuzhiyun uint8_t rsa_hash_revert[256] = {0};
84*4882a593Smuzhiyun unsigned int rsaResult_temp[8];
85*4882a593Smuzhiyun unsigned char rsaResult[32] = {0};
86*4882a593Smuzhiyun struct rk_pub_key pub_key;
87*4882a593Smuzhiyun struct udevice *dev;
88*4882a593Smuzhiyun rsa_key rsa_key;
89*4882a593Smuzhiyun char *temp;
90*4882a593Smuzhiyun int ret = 0;
91*4882a593Smuzhiyun int i;
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun memset(&pub_key, 0, sizeof(struct rk_pub_key));
94*4882a593Smuzhiyun ret = rk_avb_get_pub_key(&pub_key);
95*4882a593Smuzhiyun if (ret)
96*4882a593Smuzhiyun return false;
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun ret = rk_avb_get_perm_attr_cer(rsa_hash, 256);
99*4882a593Smuzhiyun if (ret) {
100*4882a593Smuzhiyun avb_error("get_perm_attr_cer error\n");
101*4882a593Smuzhiyun return false;
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun for (i = 0; i < 256; i++)
105*4882a593Smuzhiyun rsa_hash_revert[255-i] = rsa_hash[i];
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun dev = crypto_get_device(cap);
108*4882a593Smuzhiyun if (!dev) {
109*4882a593Smuzhiyun avb_error("Can't find crypto device for expected capability\n");
110*4882a593Smuzhiyun return false;
111*4882a593Smuzhiyun }
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun memset(&rsa_key, 0x00, sizeof(rsa_key));
114*4882a593Smuzhiyun rsa_key.algo = CRYPTO_RSA2048;
115*4882a593Smuzhiyun rsa_key.n = (u32 *)&pub_key.rsa_n;
116*4882a593Smuzhiyun rsa_key.e = (u32 *)&pub_key.rsa_e;
117*4882a593Smuzhiyun #ifdef CONFIG_ROCKCHIP_CRYPTO_V1
118*4882a593Smuzhiyun rsa_key.c = (u32 *)&pub_key.rsa_c;
119*4882a593Smuzhiyun #endif
120*4882a593Smuzhiyun ret = crypto_rsa_verify(dev, &rsa_key, (u8 *)rsa_hash_revert, (u8 *)rsaResult_temp);
121*4882a593Smuzhiyun if (ret) {
122*4882a593Smuzhiyun avb_error("Hardware verify error!\n");
123*4882a593Smuzhiyun return false;
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun temp = (char *)rsaResult_temp;
127*4882a593Smuzhiyun for (i = 0; i < 32; i++)
128*4882a593Smuzhiyun rsaResult[31-i] = temp[i];
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun sha256((const uint8_t*)attributes, sizeof(AvbAtxPermanentAttributes), hash);
131*4882a593Smuzhiyun if (memcmp((void*)rsaResult, (void*)hash, 32) == 0)
132*4882a593Smuzhiyun return true;
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun return false;
135*4882a593Smuzhiyun #endif
136*4882a593Smuzhiyun #else
137*4882a593Smuzhiyun if (attributes->version != 1) {
138*4882a593Smuzhiyun avb_error("Unsupported permanent attributes version.\n");
139*4882a593Smuzhiyun return false;
140*4882a593Smuzhiyun }
141*4882a593Smuzhiyun sha256((const uint8_t*)attributes, sizeof(AvbAtxPermanentAttributes), hash);
142*4882a593Smuzhiyun if (0 != avb_safe_memcmp(hash, expected_hash, AVB_SHA256_DIGEST_SIZE)) {
143*4882a593Smuzhiyun avb_error("Invalid permanent attributes.\n");
144*4882a593Smuzhiyun return false;
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun return true;
147*4882a593Smuzhiyun #endif
148*4882a593Smuzhiyun }
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun /* 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])151*4882a593Smuzhiyun static bool verify_certificate(
152*4882a593Smuzhiyun const AvbAtxCertificate* certificate,
153*4882a593Smuzhiyun const uint8_t authority[AVB_ATX_PUBLIC_KEY_SIZE],
154*4882a593Smuzhiyun uint64_t minimum_key_version,
155*4882a593Smuzhiyun const uint8_t expected_usage[AVB_SHA256_DIGEST_SIZE]) {
156*4882a593Smuzhiyun const AvbAlgorithmData* algorithm_data;
157*4882a593Smuzhiyun uint8_t certificate_hash[AVB_SHA512_DIGEST_SIZE];
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun if (certificate->signed_data.version != 1) {
160*4882a593Smuzhiyun avb_error("Unsupported certificate format.\n");
161*4882a593Smuzhiyun return false;
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun algorithm_data = avb_get_algorithm_data(AVB_ALGORITHM_TYPE_SHA512_RSA4096);
164*4882a593Smuzhiyun sha512((const uint8_t*)&certificate->signed_data,
165*4882a593Smuzhiyun sizeof(AvbAtxCertificateSignedData),
166*4882a593Smuzhiyun certificate_hash);
167*4882a593Smuzhiyun if (!avb_rsa_verify(authority,
168*4882a593Smuzhiyun AVB_ATX_PUBLIC_KEY_SIZE,
169*4882a593Smuzhiyun certificate->signature,
170*4882a593Smuzhiyun AVB_RSA4096_NUM_BYTES,
171*4882a593Smuzhiyun certificate_hash,
172*4882a593Smuzhiyun AVB_SHA512_DIGEST_SIZE,
173*4882a593Smuzhiyun algorithm_data->padding,
174*4882a593Smuzhiyun algorithm_data->padding_len)) {
175*4882a593Smuzhiyun avb_error("Invalid certificate signature.\n");
176*4882a593Smuzhiyun return false;
177*4882a593Smuzhiyun }
178*4882a593Smuzhiyun if (certificate->signed_data.key_version < minimum_key_version) {
179*4882a593Smuzhiyun avb_error("Key rollback detected.\n");
180*4882a593Smuzhiyun return false;
181*4882a593Smuzhiyun }
182*4882a593Smuzhiyun if (0 != avb_safe_memcmp(certificate->signed_data.usage,
183*4882a593Smuzhiyun expected_usage,
184*4882a593Smuzhiyun AVB_SHA256_DIGEST_SIZE)) {
185*4882a593Smuzhiyun avb_error("Invalid certificate usage.\n");
186*4882a593Smuzhiyun return false;
187*4882a593Smuzhiyun }
188*4882a593Smuzhiyun return true;
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun /* 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)192*4882a593Smuzhiyun static bool verify_pik_certificate(
193*4882a593Smuzhiyun const AvbAtxCertificate* certificate,
194*4882a593Smuzhiyun const uint8_t authority[AVB_ATX_PUBLIC_KEY_SIZE],
195*4882a593Smuzhiyun uint64_t minimum_version) {
196*4882a593Smuzhiyun uint8_t expected_usage[AVB_SHA256_DIGEST_SIZE];
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun sha256_str("com.google.android.things.vboot.ca", expected_usage);
199*4882a593Smuzhiyun if (!verify_certificate(
200*4882a593Smuzhiyun certificate, authority, minimum_version, expected_usage)) {
201*4882a593Smuzhiyun avb_error("Invalid PIK certificate.\n");
202*4882a593Smuzhiyun return false;
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun return true;
205*4882a593Smuzhiyun }
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun /* 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])208*4882a593Smuzhiyun static bool verify_psk_certificate(
209*4882a593Smuzhiyun const AvbAtxCertificate* certificate,
210*4882a593Smuzhiyun const uint8_t authority[AVB_ATX_PUBLIC_KEY_SIZE],
211*4882a593Smuzhiyun uint64_t minimum_version,
212*4882a593Smuzhiyun const uint8_t product_id[AVB_ATX_PRODUCT_ID_SIZE]) {
213*4882a593Smuzhiyun uint8_t expected_subject[AVB_SHA256_DIGEST_SIZE];
214*4882a593Smuzhiyun uint8_t expected_usage[AVB_SHA256_DIGEST_SIZE];
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun sha256_str("com.google.android.things.vboot", expected_usage);
217*4882a593Smuzhiyun if (!verify_certificate(
218*4882a593Smuzhiyun certificate, authority, minimum_version, expected_usage)) {
219*4882a593Smuzhiyun avb_error("Invalid PSK certificate.\n");
220*4882a593Smuzhiyun return false;
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun sha256(product_id, AVB_ATX_PRODUCT_ID_SIZE, expected_subject);
223*4882a593Smuzhiyun if (0 != avb_safe_memcmp(certificate->signed_data.subject,
224*4882a593Smuzhiyun expected_subject,
225*4882a593Smuzhiyun AVB_SHA256_DIGEST_SIZE)) {
226*4882a593Smuzhiyun avb_error("PSK: Product ID mismatch.\n");
227*4882a593Smuzhiyun return false;
228*4882a593Smuzhiyun }
229*4882a593Smuzhiyun return true;
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun /* 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])233*4882a593Smuzhiyun static bool verify_puk_certificate(
234*4882a593Smuzhiyun const AvbAtxCertificate* certificate,
235*4882a593Smuzhiyun const uint8_t authority[AVB_ATX_PUBLIC_KEY_SIZE],
236*4882a593Smuzhiyun uint64_t minimum_version,
237*4882a593Smuzhiyun const uint8_t product_id[AVB_ATX_PRODUCT_ID_SIZE]) {
238*4882a593Smuzhiyun uint8_t expected_subject[AVB_SHA256_DIGEST_SIZE];
239*4882a593Smuzhiyun uint8_t expected_usage[AVB_SHA256_DIGEST_SIZE];
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun sha256_str("com.google.android.things.vboot.unlock", expected_usage);
242*4882a593Smuzhiyun if (!verify_certificate(
243*4882a593Smuzhiyun certificate, authority, minimum_version, expected_usage)) {
244*4882a593Smuzhiyun avb_error("Invalid PUK certificate.\n");
245*4882a593Smuzhiyun return false;
246*4882a593Smuzhiyun }
247*4882a593Smuzhiyun sha256(product_id, AVB_ATX_PRODUCT_ID_SIZE, expected_subject);
248*4882a593Smuzhiyun if (0 != avb_safe_memcmp(certificate->signed_data.subject,
249*4882a593Smuzhiyun expected_subject,
250*4882a593Smuzhiyun AVB_SHA256_DIGEST_SIZE)) {
251*4882a593Smuzhiyun avb_error("PUK: Product ID mismatch.\n");
252*4882a593Smuzhiyun return false;
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun return true;
255*4882a593Smuzhiyun }
256*4882a593Smuzhiyun
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)257*4882a593Smuzhiyun AvbIOResult avb_atx_validate_vbmeta_public_key(
258*4882a593Smuzhiyun AvbOps* ops,
259*4882a593Smuzhiyun const uint8_t* public_key_data,
260*4882a593Smuzhiyun size_t public_key_length,
261*4882a593Smuzhiyun const uint8_t* public_key_metadata,
262*4882a593Smuzhiyun size_t public_key_metadata_length,
263*4882a593Smuzhiyun bool* out_is_trusted) {
264*4882a593Smuzhiyun AvbIOResult result = AVB_IO_RESULT_OK;
265*4882a593Smuzhiyun AvbAtxPermanentAttributes permanent_attributes;
266*4882a593Smuzhiyun uint8_t permanent_attributes_hash[AVB_SHA256_DIGEST_SIZE];
267*4882a593Smuzhiyun AvbAtxPublicKeyMetadata metadata;
268*4882a593Smuzhiyun uint64_t minimum_version;
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun /* Be pessimistic so we can exit early without having to remember to clear.
271*4882a593Smuzhiyun */
272*4882a593Smuzhiyun *out_is_trusted = false;
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun /* Read and verify permanent attributes. */
275*4882a593Smuzhiyun result = ops->atx_ops->read_permanent_attributes(ops->atx_ops,
276*4882a593Smuzhiyun &permanent_attributes);
277*4882a593Smuzhiyun if (result != AVB_IO_RESULT_OK) {
278*4882a593Smuzhiyun avb_error("Failed to read permanent attributes.\n");
279*4882a593Smuzhiyun return result;
280*4882a593Smuzhiyun }
281*4882a593Smuzhiyun result = ops->atx_ops->read_permanent_attributes_hash(
282*4882a593Smuzhiyun ops->atx_ops, permanent_attributes_hash);
283*4882a593Smuzhiyun if (result != AVB_IO_RESULT_OK) {
284*4882a593Smuzhiyun avb_error("Failed to read permanent attributes hash.\n");
285*4882a593Smuzhiyun return result;
286*4882a593Smuzhiyun }
287*4882a593Smuzhiyun if (!verify_permanent_attributes(&permanent_attributes,
288*4882a593Smuzhiyun permanent_attributes_hash)) {
289*4882a593Smuzhiyun return AVB_IO_RESULT_OK;
290*4882a593Smuzhiyun }
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun /* Sanity check public key metadata. */
293*4882a593Smuzhiyun if (public_key_metadata_length != sizeof(AvbAtxPublicKeyMetadata)) {
294*4882a593Smuzhiyun avb_error("Invalid public key metadata.\n");
295*4882a593Smuzhiyun return AVB_IO_RESULT_OK;
296*4882a593Smuzhiyun }
297*4882a593Smuzhiyun avb_memcpy(&metadata, public_key_metadata, sizeof(AvbAtxPublicKeyMetadata));
298*4882a593Smuzhiyun if (metadata.version != 1) {
299*4882a593Smuzhiyun avb_error("Unsupported public key metadata.\n");
300*4882a593Smuzhiyun return AVB_IO_RESULT_OK;
301*4882a593Smuzhiyun }
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun /* Verify the PIK certificate. */
304*4882a593Smuzhiyun result = ops->read_rollback_index(
305*4882a593Smuzhiyun ops, AVB_ATX_PIK_VERSION_LOCATION, &minimum_version);
306*4882a593Smuzhiyun if (result != AVB_IO_RESULT_OK) {
307*4882a593Smuzhiyun avb_error("Failed to read PIK minimum version.\n");
308*4882a593Smuzhiyun return result;
309*4882a593Smuzhiyun }
310*4882a593Smuzhiyun if (!verify_pik_certificate(&metadata.product_intermediate_key_certificate,
311*4882a593Smuzhiyun permanent_attributes.product_root_public_key,
312*4882a593Smuzhiyun minimum_version)) {
313*4882a593Smuzhiyun return AVB_IO_RESULT_OK;
314*4882a593Smuzhiyun }
315*4882a593Smuzhiyun
316*4882a593Smuzhiyun /* Verify the PSK certificate. */
317*4882a593Smuzhiyun result = ops->read_rollback_index(
318*4882a593Smuzhiyun ops, AVB_ATX_PSK_VERSION_LOCATION, &minimum_version);
319*4882a593Smuzhiyun if (result != AVB_IO_RESULT_OK) {
320*4882a593Smuzhiyun avb_error("Failed to read PSK minimum version.\n");
321*4882a593Smuzhiyun return result;
322*4882a593Smuzhiyun }
323*4882a593Smuzhiyun if (!verify_psk_certificate(
324*4882a593Smuzhiyun &metadata.product_signing_key_certificate,
325*4882a593Smuzhiyun metadata.product_intermediate_key_certificate.signed_data.public_key,
326*4882a593Smuzhiyun minimum_version,
327*4882a593Smuzhiyun permanent_attributes.product_id)) {
328*4882a593Smuzhiyun return AVB_IO_RESULT_OK;
329*4882a593Smuzhiyun }
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun /* Verify the PSK is the same key that verified vbmeta. */
332*4882a593Smuzhiyun if (public_key_length != AVB_ATX_PUBLIC_KEY_SIZE) {
333*4882a593Smuzhiyun avb_error("Public key length mismatch.\n");
334*4882a593Smuzhiyun return AVB_IO_RESULT_OK;
335*4882a593Smuzhiyun }
336*4882a593Smuzhiyun if (0 != avb_safe_memcmp(
337*4882a593Smuzhiyun metadata.product_signing_key_certificate.signed_data.public_key,
338*4882a593Smuzhiyun public_key_data,
339*4882a593Smuzhiyun AVB_ATX_PUBLIC_KEY_SIZE)) {
340*4882a593Smuzhiyun avb_error("Public key mismatch.\n");
341*4882a593Smuzhiyun return AVB_IO_RESULT_OK;
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun /* Report the key versions used during verification. */
345*4882a593Smuzhiyun ops->atx_ops->set_key_version(
346*4882a593Smuzhiyun ops->atx_ops,
347*4882a593Smuzhiyun AVB_ATX_PIK_VERSION_LOCATION,
348*4882a593Smuzhiyun metadata.product_intermediate_key_certificate.signed_data.key_version);
349*4882a593Smuzhiyun ops->atx_ops->set_key_version(
350*4882a593Smuzhiyun ops->atx_ops,
351*4882a593Smuzhiyun AVB_ATX_PSK_VERSION_LOCATION,
352*4882a593Smuzhiyun metadata.product_signing_key_certificate.signed_data.key_version);
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun *out_is_trusted = true;
355*4882a593Smuzhiyun return AVB_IO_RESULT_OK;
356*4882a593Smuzhiyun }
357*4882a593Smuzhiyun
avb_atx_generate_unlock_challenge(AvbAtxOps * atx_ops,AvbAtxUnlockChallenge * out_unlock_challenge)358*4882a593Smuzhiyun AvbIOResult avb_atx_generate_unlock_challenge(
359*4882a593Smuzhiyun AvbAtxOps* atx_ops, AvbAtxUnlockChallenge* out_unlock_challenge) {
360*4882a593Smuzhiyun AvbIOResult result = AVB_IO_RESULT_OK;
361*4882a593Smuzhiyun AvbAtxPermanentAttributes permanent_attributes;
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun /* We need the permanent attributes to compute the product_id_hash. */
364*4882a593Smuzhiyun result = atx_ops->read_permanent_attributes(atx_ops, &permanent_attributes);
365*4882a593Smuzhiyun if (result != AVB_IO_RESULT_OK) {
366*4882a593Smuzhiyun avb_error("Failed to read permanent attributes.\n");
367*4882a593Smuzhiyun return result;
368*4882a593Smuzhiyun }
369*4882a593Smuzhiyun result = atx_ops->get_random(
370*4882a593Smuzhiyun atx_ops, AVB_ATX_UNLOCK_CHALLENGE_SIZE, last_unlock_challenge);
371*4882a593Smuzhiyun if (result != AVB_IO_RESULT_OK) {
372*4882a593Smuzhiyun avb_error("Failed to generate random challenge.\n");
373*4882a593Smuzhiyun return result;
374*4882a593Smuzhiyun }
375*4882a593Smuzhiyun last_unlock_challenge_set = true;
376*4882a593Smuzhiyun out_unlock_challenge->version = 1;
377*4882a593Smuzhiyun sha256(permanent_attributes.product_id,
378*4882a593Smuzhiyun AVB_ATX_PRODUCT_ID_SIZE,
379*4882a593Smuzhiyun out_unlock_challenge->product_id_hash);
380*4882a593Smuzhiyun avb_memcpy(out_unlock_challenge->challenge,
381*4882a593Smuzhiyun last_unlock_challenge,
382*4882a593Smuzhiyun AVB_ATX_UNLOCK_CHALLENGE_SIZE);
383*4882a593Smuzhiyun return result;
384*4882a593Smuzhiyun }
385*4882a593Smuzhiyun
avb_atx_validate_unlock_credential(AvbAtxOps * atx_ops,const AvbAtxUnlockCredential * unlock_credential,bool * out_is_trusted)386*4882a593Smuzhiyun AvbIOResult avb_atx_validate_unlock_credential(
387*4882a593Smuzhiyun AvbAtxOps* atx_ops,
388*4882a593Smuzhiyun const AvbAtxUnlockCredential* unlock_credential,
389*4882a593Smuzhiyun bool* out_is_trusted) {
390*4882a593Smuzhiyun AvbIOResult result = AVB_IO_RESULT_OK;
391*4882a593Smuzhiyun AvbAtxPermanentAttributes permanent_attributes;
392*4882a593Smuzhiyun uint8_t permanent_attributes_hash[AVB_SHA256_DIGEST_SIZE];
393*4882a593Smuzhiyun uint64_t minimum_version;
394*4882a593Smuzhiyun const AvbAlgorithmData* algorithm_data;
395*4882a593Smuzhiyun uint8_t challenge_hash[AVB_SHA512_DIGEST_SIZE];
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun /* Be pessimistic so we can exit early without having to remember to clear.
398*4882a593Smuzhiyun */
399*4882a593Smuzhiyun *out_is_trusted = false;
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun /* Sanity check the credential. */
402*4882a593Smuzhiyun if (unlock_credential->version != 1) {
403*4882a593Smuzhiyun avb_error("Unsupported unlock credential format.\n");
404*4882a593Smuzhiyun return AVB_IO_RESULT_OK;
405*4882a593Smuzhiyun }
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun /* Read and verify permanent attributes. */
408*4882a593Smuzhiyun result = atx_ops->read_permanent_attributes(atx_ops, &permanent_attributes);
409*4882a593Smuzhiyun if (result != AVB_IO_RESULT_OK) {
410*4882a593Smuzhiyun avb_error("Failed to read permanent attributes.\n");
411*4882a593Smuzhiyun return result;
412*4882a593Smuzhiyun }
413*4882a593Smuzhiyun result = atx_ops->read_permanent_attributes_hash(atx_ops,
414*4882a593Smuzhiyun permanent_attributes_hash);
415*4882a593Smuzhiyun if (result != AVB_IO_RESULT_OK) {
416*4882a593Smuzhiyun avb_error("Failed to read permanent attributes hash.\n");
417*4882a593Smuzhiyun return result;
418*4882a593Smuzhiyun }
419*4882a593Smuzhiyun if (!verify_permanent_attributes(&permanent_attributes,
420*4882a593Smuzhiyun permanent_attributes_hash)) {
421*4882a593Smuzhiyun return AVB_IO_RESULT_OK;
422*4882a593Smuzhiyun }
423*4882a593Smuzhiyun
424*4882a593Smuzhiyun /* Verify the PIK certificate. */
425*4882a593Smuzhiyun result = atx_ops->ops->read_rollback_index(
426*4882a593Smuzhiyun atx_ops->ops, AVB_ATX_PIK_VERSION_LOCATION, &minimum_version);
427*4882a593Smuzhiyun if (result != AVB_IO_RESULT_OK) {
428*4882a593Smuzhiyun avb_error("Failed to read PIK minimum version.\n");
429*4882a593Smuzhiyun return result;
430*4882a593Smuzhiyun }
431*4882a593Smuzhiyun if (!verify_pik_certificate(
432*4882a593Smuzhiyun &unlock_credential->product_intermediate_key_certificate,
433*4882a593Smuzhiyun permanent_attributes.product_root_public_key,
434*4882a593Smuzhiyun minimum_version)) {
435*4882a593Smuzhiyun return AVB_IO_RESULT_OK;
436*4882a593Smuzhiyun }
437*4882a593Smuzhiyun
438*4882a593Smuzhiyun /* Verify the PUK certificate. The minimum version is shared with the PSK. */
439*4882a593Smuzhiyun result = atx_ops->ops->read_rollback_index(
440*4882a593Smuzhiyun atx_ops->ops, AVB_ATX_PSK_VERSION_LOCATION, &minimum_version);
441*4882a593Smuzhiyun if (result != AVB_IO_RESULT_OK) {
442*4882a593Smuzhiyun avb_error("Failed to read PSK minimum version.\n");
443*4882a593Smuzhiyun return result;
444*4882a593Smuzhiyun }
445*4882a593Smuzhiyun if (!verify_puk_certificate(
446*4882a593Smuzhiyun &unlock_credential->product_unlock_key_certificate,
447*4882a593Smuzhiyun unlock_credential->product_intermediate_key_certificate.signed_data
448*4882a593Smuzhiyun .public_key,
449*4882a593Smuzhiyun minimum_version,
450*4882a593Smuzhiyun permanent_attributes.product_id)) {
451*4882a593Smuzhiyun return AVB_IO_RESULT_OK;
452*4882a593Smuzhiyun }
453*4882a593Smuzhiyun
454*4882a593Smuzhiyun /* Hash the most recent unlock challenge. */
455*4882a593Smuzhiyun if (!last_unlock_challenge_set) {
456*4882a593Smuzhiyun avb_error("Challenge does not exist.\n");
457*4882a593Smuzhiyun return AVB_IO_RESULT_OK;
458*4882a593Smuzhiyun }
459*4882a593Smuzhiyun sha512(last_unlock_challenge, AVB_ATX_UNLOCK_CHALLENGE_SIZE, challenge_hash);
460*4882a593Smuzhiyun last_unlock_challenge_set = false;
461*4882a593Smuzhiyun
462*4882a593Smuzhiyun /* Verify the challenge signature. */
463*4882a593Smuzhiyun algorithm_data = avb_get_algorithm_data(AVB_ALGORITHM_TYPE_SHA512_RSA4096);
464*4882a593Smuzhiyun if (!avb_rsa_verify(unlock_credential->product_unlock_key_certificate
465*4882a593Smuzhiyun .signed_data.public_key,
466*4882a593Smuzhiyun AVB_ATX_PUBLIC_KEY_SIZE,
467*4882a593Smuzhiyun unlock_credential->challenge_signature,
468*4882a593Smuzhiyun AVB_RSA4096_NUM_BYTES,
469*4882a593Smuzhiyun challenge_hash,
470*4882a593Smuzhiyun AVB_SHA512_DIGEST_SIZE,
471*4882a593Smuzhiyun algorithm_data->padding,
472*4882a593Smuzhiyun algorithm_data->padding_len)) {
473*4882a593Smuzhiyun avb_error("Invalid unlock challenge signature.\n");
474*4882a593Smuzhiyun return AVB_IO_RESULT_OK;
475*4882a593Smuzhiyun }
476*4882a593Smuzhiyun
477*4882a593Smuzhiyun *out_is_trusted = true;
478*4882a593Smuzhiyun return AVB_IO_RESULT_OK;
479*4882a593Smuzhiyun }
480