1*d289c2baSAndroid Build Coastguard Worker /*
2*d289c2baSAndroid Build Coastguard Worker * Copyright (C) 2016 The Android Open Source Project
3*d289c2baSAndroid Build Coastguard Worker *
4*d289c2baSAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person
5*d289c2baSAndroid Build Coastguard Worker * obtaining a copy of this software and associated documentation
6*d289c2baSAndroid Build Coastguard Worker * files (the "Software"), to deal in the Software without
7*d289c2baSAndroid Build Coastguard Worker * restriction, including without limitation the rights to use, copy,
8*d289c2baSAndroid Build Coastguard Worker * modify, merge, publish, distribute, sublicense, and/or sell copies
9*d289c2baSAndroid Build Coastguard Worker * of the Software, and to permit persons to whom the Software is
10*d289c2baSAndroid Build Coastguard Worker * furnished to do so, subject to the following conditions:
11*d289c2baSAndroid Build Coastguard Worker *
12*d289c2baSAndroid Build Coastguard Worker * The above copyright notice and this permission notice shall be
13*d289c2baSAndroid Build Coastguard Worker * included in all copies or substantial portions of the Software.
14*d289c2baSAndroid Build Coastguard Worker *
15*d289c2baSAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16*d289c2baSAndroid Build Coastguard Worker * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17*d289c2baSAndroid Build Coastguard Worker * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18*d289c2baSAndroid Build Coastguard Worker * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19*d289c2baSAndroid Build Coastguard Worker * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20*d289c2baSAndroid Build Coastguard Worker * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21*d289c2baSAndroid Build Coastguard Worker * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22*d289c2baSAndroid Build Coastguard Worker * SOFTWARE.
23*d289c2baSAndroid Build Coastguard Worker */
24*d289c2baSAndroid Build Coastguard Worker
25*d289c2baSAndroid Build Coastguard Worker #include "avb_cert_validate.h"
26*d289c2baSAndroid Build Coastguard Worker
27*d289c2baSAndroid Build Coastguard Worker #include <libavb/avb_rsa.h>
28*d289c2baSAndroid Build Coastguard Worker #include <libavb/avb_sha.h>
29*d289c2baSAndroid Build Coastguard Worker #include <libavb/avb_sysdeps.h>
30*d289c2baSAndroid Build Coastguard Worker #include <libavb/avb_util.h>
31*d289c2baSAndroid Build Coastguard Worker
32*d289c2baSAndroid Build Coastguard Worker /* Pre-computed SHA256 hashes for the known usage strings.
33*d289c2baSAndroid Build Coastguard Worker * Usage strings must match certs generated by avbtool.py. */
34*d289c2baSAndroid Build Coastguard Worker /* com.google.android.things.vboot */
35*d289c2baSAndroid Build Coastguard Worker const uint8_t CERT_USAGE_HASH_SIGNING[AVB_SHA256_DIGEST_SIZE] = {
36*d289c2baSAndroid Build Coastguard Worker 0x75, 0x04, 0x7f, 0xe1, 0x5e, 0xd4, 0x99, 0x80, 0x2d, 0xfd, 0x77,
37*d289c2baSAndroid Build Coastguard Worker 0x26, 0x00, 0x61, 0x18, 0xef, 0x5b, 0x06, 0x58, 0x56, 0xf5, 0x9c,
38*d289c2baSAndroid Build Coastguard Worker 0xa7, 0xf4, 0xdc, 0x63, 0xe7, 0x59, 0xe6, 0x48, 0xf8, 0x16};
39*d289c2baSAndroid Build Coastguard Worker /* com.google.android.things.vboot.ca */
40*d289c2baSAndroid Build Coastguard Worker const uint8_t CERT_USAGE_HASH_INTERMEDIATE_AUTHORITY[AVB_SHA256_DIGEST_SIZE] = {
41*d289c2baSAndroid Build Coastguard Worker 0x04, 0xec, 0x7c, 0xc7, 0x42, 0x41, 0x76, 0x3b, 0xcc, 0x72, 0xe3,
42*d289c2baSAndroid Build Coastguard Worker 0x5e, 0xd3, 0x92, 0xdf, 0xd8, 0x2a, 0x6c, 0x51, 0xae, 0xa8, 0xec,
43*d289c2baSAndroid Build Coastguard Worker 0x6d, 0x43, 0x27, 0xc7, 0x0d, 0xf4, 0x53, 0x4b, 0x21, 0x5c};
44*d289c2baSAndroid Build Coastguard Worker /* com.google.android.things.vboot.unlock */
45*d289c2baSAndroid Build Coastguard Worker const uint8_t CERT_USAGE_HASH_UNLOCK[AVB_SHA256_DIGEST_SIZE] = {
46*d289c2baSAndroid Build Coastguard Worker 0x7b, 0x84, 0x6c, 0x4a, 0xfd, 0x85, 0x48, 0x8f, 0x42, 0x9b, 0x7a,
47*d289c2baSAndroid Build Coastguard Worker 0xcf, 0x93, 0xcf, 0x6a, 0xff, 0x5c, 0x50, 0x28, 0x1b, 0xbf, 0x9b,
48*d289c2baSAndroid Build Coastguard Worker 0xd7, 0xb0, 0x18, 0xa5, 0x24, 0x2a, 0x86, 0x0d, 0xe3, 0xf8};
49*d289c2baSAndroid Build Coastguard Worker
50*d289c2baSAndroid Build Coastguard Worker /* The most recent unlock challenge generated. */
51*d289c2baSAndroid Build Coastguard Worker static uint8_t last_unlock_challenge[AVB_CERT_UNLOCK_CHALLENGE_SIZE];
52*d289c2baSAndroid Build Coastguard Worker static bool last_unlock_challenge_set = false;
53*d289c2baSAndroid Build Coastguard Worker
54*d289c2baSAndroid Build Coastguard Worker /* Computes the SHA256 |hash| of |length| bytes of |data|. */
sha256(const uint8_t * data,uint32_t length,uint8_t hash[AVB_SHA256_DIGEST_SIZE])55*d289c2baSAndroid Build Coastguard Worker static void sha256(const uint8_t* data,
56*d289c2baSAndroid Build Coastguard Worker uint32_t length,
57*d289c2baSAndroid Build Coastguard Worker uint8_t hash[AVB_SHA256_DIGEST_SIZE]) {
58*d289c2baSAndroid Build Coastguard Worker AvbSHA256Ctx context;
59*d289c2baSAndroid Build Coastguard Worker avb_sha256_init(&context);
60*d289c2baSAndroid Build Coastguard Worker avb_sha256_update(&context, data, length);
61*d289c2baSAndroid Build Coastguard Worker uint8_t* tmp = avb_sha256_final(&context);
62*d289c2baSAndroid Build Coastguard Worker avb_memcpy(hash, tmp, AVB_SHA256_DIGEST_SIZE);
63*d289c2baSAndroid Build Coastguard Worker }
64*d289c2baSAndroid Build Coastguard Worker
65*d289c2baSAndroid Build Coastguard Worker /* Computes the SHA512 |hash| of |length| bytes of |data|. */
sha512(const uint8_t * data,uint32_t length,uint8_t hash[AVB_SHA512_DIGEST_SIZE])66*d289c2baSAndroid Build Coastguard Worker static void sha512(const uint8_t* data,
67*d289c2baSAndroid Build Coastguard Worker uint32_t length,
68*d289c2baSAndroid Build Coastguard Worker uint8_t hash[AVB_SHA512_DIGEST_SIZE]) {
69*d289c2baSAndroid Build Coastguard Worker AvbSHA512Ctx context;
70*d289c2baSAndroid Build Coastguard Worker avb_sha512_init(&context);
71*d289c2baSAndroid Build Coastguard Worker avb_sha512_update(&context, data, length);
72*d289c2baSAndroid Build Coastguard Worker uint8_t* tmp = avb_sha512_final(&context);
73*d289c2baSAndroid Build Coastguard Worker avb_memcpy(hash, tmp, AVB_SHA512_DIGEST_SIZE);
74*d289c2baSAndroid Build Coastguard Worker }
75*d289c2baSAndroid Build Coastguard Worker
76*d289c2baSAndroid Build Coastguard Worker /* Verifies structure and |expected_hash| of permanent |attributes|. */
verify_permanent_attributes(const AvbCertPermanentAttributes * attributes,const uint8_t expected_hash[AVB_SHA256_DIGEST_SIZE])77*d289c2baSAndroid Build Coastguard Worker static bool verify_permanent_attributes(
78*d289c2baSAndroid Build Coastguard Worker const AvbCertPermanentAttributes* attributes,
79*d289c2baSAndroid Build Coastguard Worker const uint8_t expected_hash[AVB_SHA256_DIGEST_SIZE]) {
80*d289c2baSAndroid Build Coastguard Worker uint8_t hash[AVB_SHA256_DIGEST_SIZE];
81*d289c2baSAndroid Build Coastguard Worker
82*d289c2baSAndroid Build Coastguard Worker if (attributes->version != 1) {
83*d289c2baSAndroid Build Coastguard Worker avb_error("Unsupported permanent attributes version.\n");
84*d289c2baSAndroid Build Coastguard Worker return false;
85*d289c2baSAndroid Build Coastguard Worker }
86*d289c2baSAndroid Build Coastguard Worker sha256((const uint8_t*)attributes, sizeof(AvbCertPermanentAttributes), hash);
87*d289c2baSAndroid Build Coastguard Worker if (0 != avb_safe_memcmp(hash, expected_hash, AVB_SHA256_DIGEST_SIZE)) {
88*d289c2baSAndroid Build Coastguard Worker avb_error("Invalid permanent attributes.\n");
89*d289c2baSAndroid Build Coastguard Worker return false;
90*d289c2baSAndroid Build Coastguard Worker }
91*d289c2baSAndroid Build Coastguard Worker return true;
92*d289c2baSAndroid Build Coastguard Worker }
93*d289c2baSAndroid Build Coastguard Worker
94*d289c2baSAndroid Build Coastguard Worker /* Verifies the format, key version, usage, and signature of a certificate. */
verify_certificate(const AvbCertCertificate * certificate,const uint8_t authority[AVB_CERT_PUBLIC_KEY_SIZE],uint64_t minimum_key_version,const uint8_t expected_usage[AVB_SHA256_DIGEST_SIZE])95*d289c2baSAndroid Build Coastguard Worker static bool verify_certificate(
96*d289c2baSAndroid Build Coastguard Worker const AvbCertCertificate* certificate,
97*d289c2baSAndroid Build Coastguard Worker const uint8_t authority[AVB_CERT_PUBLIC_KEY_SIZE],
98*d289c2baSAndroid Build Coastguard Worker uint64_t minimum_key_version,
99*d289c2baSAndroid Build Coastguard Worker const uint8_t expected_usage[AVB_SHA256_DIGEST_SIZE]) {
100*d289c2baSAndroid Build Coastguard Worker const AvbAlgorithmData* algorithm_data;
101*d289c2baSAndroid Build Coastguard Worker uint8_t certificate_hash[AVB_SHA512_DIGEST_SIZE];
102*d289c2baSAndroid Build Coastguard Worker
103*d289c2baSAndroid Build Coastguard Worker if (certificate->signed_data.version != 1) {
104*d289c2baSAndroid Build Coastguard Worker avb_error("Unsupported certificate format.\n");
105*d289c2baSAndroid Build Coastguard Worker return false;
106*d289c2baSAndroid Build Coastguard Worker }
107*d289c2baSAndroid Build Coastguard Worker algorithm_data = avb_get_algorithm_data(AVB_ALGORITHM_TYPE_SHA512_RSA4096);
108*d289c2baSAndroid Build Coastguard Worker sha512((const uint8_t*)&certificate->signed_data,
109*d289c2baSAndroid Build Coastguard Worker sizeof(AvbCertCertificateSignedData),
110*d289c2baSAndroid Build Coastguard Worker certificate_hash);
111*d289c2baSAndroid Build Coastguard Worker if (!avb_rsa_verify(authority,
112*d289c2baSAndroid Build Coastguard Worker AVB_CERT_PUBLIC_KEY_SIZE,
113*d289c2baSAndroid Build Coastguard Worker certificate->signature,
114*d289c2baSAndroid Build Coastguard Worker AVB_RSA4096_NUM_BYTES,
115*d289c2baSAndroid Build Coastguard Worker certificate_hash,
116*d289c2baSAndroid Build Coastguard Worker AVB_SHA512_DIGEST_SIZE,
117*d289c2baSAndroid Build Coastguard Worker algorithm_data->padding,
118*d289c2baSAndroid Build Coastguard Worker algorithm_data->padding_len)) {
119*d289c2baSAndroid Build Coastguard Worker avb_error("Invalid certificate signature.\n");
120*d289c2baSAndroid Build Coastguard Worker return false;
121*d289c2baSAndroid Build Coastguard Worker }
122*d289c2baSAndroid Build Coastguard Worker if (certificate->signed_data.key_version < minimum_key_version) {
123*d289c2baSAndroid Build Coastguard Worker avb_error("Key rollback detected.\n");
124*d289c2baSAndroid Build Coastguard Worker return false;
125*d289c2baSAndroid Build Coastguard Worker }
126*d289c2baSAndroid Build Coastguard Worker if (0 != avb_safe_memcmp(certificate->signed_data.usage,
127*d289c2baSAndroid Build Coastguard Worker expected_usage,
128*d289c2baSAndroid Build Coastguard Worker AVB_SHA256_DIGEST_SIZE)) {
129*d289c2baSAndroid Build Coastguard Worker avb_error("Invalid certificate usage.\n");
130*d289c2baSAndroid Build Coastguard Worker return false;
131*d289c2baSAndroid Build Coastguard Worker }
132*d289c2baSAndroid Build Coastguard Worker return true;
133*d289c2baSAndroid Build Coastguard Worker }
134*d289c2baSAndroid Build Coastguard Worker
135*d289c2baSAndroid Build Coastguard Worker /* Verifies signature and fields of a PIK certificate. */
verify_pik_certificate(const AvbCertCertificate * certificate,const uint8_t authority[AVB_CERT_PUBLIC_KEY_SIZE],uint64_t minimum_version)136*d289c2baSAndroid Build Coastguard Worker static bool verify_pik_certificate(
137*d289c2baSAndroid Build Coastguard Worker const AvbCertCertificate* certificate,
138*d289c2baSAndroid Build Coastguard Worker const uint8_t authority[AVB_CERT_PUBLIC_KEY_SIZE],
139*d289c2baSAndroid Build Coastguard Worker uint64_t minimum_version) {
140*d289c2baSAndroid Build Coastguard Worker if (!verify_certificate(certificate,
141*d289c2baSAndroid Build Coastguard Worker authority,
142*d289c2baSAndroid Build Coastguard Worker minimum_version,
143*d289c2baSAndroid Build Coastguard Worker CERT_USAGE_HASH_INTERMEDIATE_AUTHORITY)) {
144*d289c2baSAndroid Build Coastguard Worker avb_error("Invalid PIK certificate.\n");
145*d289c2baSAndroid Build Coastguard Worker return false;
146*d289c2baSAndroid Build Coastguard Worker }
147*d289c2baSAndroid Build Coastguard Worker return true;
148*d289c2baSAndroid Build Coastguard Worker }
149*d289c2baSAndroid Build Coastguard Worker
150*d289c2baSAndroid Build Coastguard Worker /* Verifies signature and fields of a PSK certificate. */
verify_psk_certificate(const AvbCertCertificate * certificate,const uint8_t authority[AVB_CERT_PUBLIC_KEY_SIZE],uint64_t minimum_version,const uint8_t product_id[AVB_CERT_PRODUCT_ID_SIZE])151*d289c2baSAndroid Build Coastguard Worker static bool verify_psk_certificate(
152*d289c2baSAndroid Build Coastguard Worker const AvbCertCertificate* certificate,
153*d289c2baSAndroid Build Coastguard Worker const uint8_t authority[AVB_CERT_PUBLIC_KEY_SIZE],
154*d289c2baSAndroid Build Coastguard Worker uint64_t minimum_version,
155*d289c2baSAndroid Build Coastguard Worker const uint8_t product_id[AVB_CERT_PRODUCT_ID_SIZE]) {
156*d289c2baSAndroid Build Coastguard Worker uint8_t expected_subject[AVB_SHA256_DIGEST_SIZE];
157*d289c2baSAndroid Build Coastguard Worker
158*d289c2baSAndroid Build Coastguard Worker if (!verify_certificate(
159*d289c2baSAndroid Build Coastguard Worker certificate, authority, minimum_version, CERT_USAGE_HASH_SIGNING)) {
160*d289c2baSAndroid Build Coastguard Worker avb_error("Invalid PSK certificate.\n");
161*d289c2baSAndroid Build Coastguard Worker return false;
162*d289c2baSAndroid Build Coastguard Worker }
163*d289c2baSAndroid Build Coastguard Worker sha256(product_id, AVB_CERT_PRODUCT_ID_SIZE, expected_subject);
164*d289c2baSAndroid Build Coastguard Worker if (0 != avb_safe_memcmp(certificate->signed_data.subject,
165*d289c2baSAndroid Build Coastguard Worker expected_subject,
166*d289c2baSAndroid Build Coastguard Worker AVB_SHA256_DIGEST_SIZE)) {
167*d289c2baSAndroid Build Coastguard Worker avb_error("PSK: Product ID mismatch.\n");
168*d289c2baSAndroid Build Coastguard Worker return false;
169*d289c2baSAndroid Build Coastguard Worker }
170*d289c2baSAndroid Build Coastguard Worker return true;
171*d289c2baSAndroid Build Coastguard Worker }
172*d289c2baSAndroid Build Coastguard Worker
173*d289c2baSAndroid Build Coastguard Worker /* Verifies signature and fields of a PUK certificate. */
verify_puk_certificate(const AvbCertCertificate * certificate,const uint8_t authority[AVB_CERT_PUBLIC_KEY_SIZE],uint64_t minimum_version,const uint8_t product_id[AVB_CERT_PRODUCT_ID_SIZE])174*d289c2baSAndroid Build Coastguard Worker static bool verify_puk_certificate(
175*d289c2baSAndroid Build Coastguard Worker const AvbCertCertificate* certificate,
176*d289c2baSAndroid Build Coastguard Worker const uint8_t authority[AVB_CERT_PUBLIC_KEY_SIZE],
177*d289c2baSAndroid Build Coastguard Worker uint64_t minimum_version,
178*d289c2baSAndroid Build Coastguard Worker const uint8_t product_id[AVB_CERT_PRODUCT_ID_SIZE]) {
179*d289c2baSAndroid Build Coastguard Worker uint8_t expected_subject[AVB_SHA256_DIGEST_SIZE];
180*d289c2baSAndroid Build Coastguard Worker
181*d289c2baSAndroid Build Coastguard Worker if (!verify_certificate(
182*d289c2baSAndroid Build Coastguard Worker certificate, authority, minimum_version, CERT_USAGE_HASH_UNLOCK)) {
183*d289c2baSAndroid Build Coastguard Worker avb_error("Invalid PUK certificate.\n");
184*d289c2baSAndroid Build Coastguard Worker return false;
185*d289c2baSAndroid Build Coastguard Worker }
186*d289c2baSAndroid Build Coastguard Worker sha256(product_id, AVB_CERT_PRODUCT_ID_SIZE, expected_subject);
187*d289c2baSAndroid Build Coastguard Worker if (0 != avb_safe_memcmp(certificate->signed_data.subject,
188*d289c2baSAndroid Build Coastguard Worker expected_subject,
189*d289c2baSAndroid Build Coastguard Worker AVB_SHA256_DIGEST_SIZE)) {
190*d289c2baSAndroid Build Coastguard Worker avb_error("PUK: Product ID mismatch.\n");
191*d289c2baSAndroid Build Coastguard Worker return false;
192*d289c2baSAndroid Build Coastguard Worker }
193*d289c2baSAndroid Build Coastguard Worker return true;
194*d289c2baSAndroid Build Coastguard Worker }
195*d289c2baSAndroid Build Coastguard Worker
avb_cert_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)196*d289c2baSAndroid Build Coastguard Worker AvbIOResult avb_cert_validate_vbmeta_public_key(
197*d289c2baSAndroid Build Coastguard Worker AvbOps* ops,
198*d289c2baSAndroid Build Coastguard Worker const uint8_t* public_key_data,
199*d289c2baSAndroid Build Coastguard Worker size_t public_key_length,
200*d289c2baSAndroid Build Coastguard Worker const uint8_t* public_key_metadata,
201*d289c2baSAndroid Build Coastguard Worker size_t public_key_metadata_length,
202*d289c2baSAndroid Build Coastguard Worker bool* out_is_trusted) {
203*d289c2baSAndroid Build Coastguard Worker AvbIOResult result = AVB_IO_RESULT_OK;
204*d289c2baSAndroid Build Coastguard Worker AvbCertPermanentAttributes permanent_attributes;
205*d289c2baSAndroid Build Coastguard Worker uint8_t permanent_attributes_hash[AVB_SHA256_DIGEST_SIZE];
206*d289c2baSAndroid Build Coastguard Worker AvbCertPublicKeyMetadata metadata;
207*d289c2baSAndroid Build Coastguard Worker uint64_t minimum_version;
208*d289c2baSAndroid Build Coastguard Worker
209*d289c2baSAndroid Build Coastguard Worker /* Be pessimistic so we can exit early without having to remember to clear.
210*d289c2baSAndroid Build Coastguard Worker */
211*d289c2baSAndroid Build Coastguard Worker *out_is_trusted = false;
212*d289c2baSAndroid Build Coastguard Worker
213*d289c2baSAndroid Build Coastguard Worker /* Read and verify permanent attributes. */
214*d289c2baSAndroid Build Coastguard Worker result = ops->cert_ops->read_permanent_attributes(ops->cert_ops,
215*d289c2baSAndroid Build Coastguard Worker &permanent_attributes);
216*d289c2baSAndroid Build Coastguard Worker if (result != AVB_IO_RESULT_OK) {
217*d289c2baSAndroid Build Coastguard Worker avb_error("Failed to read permanent attributes.\n");
218*d289c2baSAndroid Build Coastguard Worker return result;
219*d289c2baSAndroid Build Coastguard Worker }
220*d289c2baSAndroid Build Coastguard Worker result = ops->cert_ops->read_permanent_attributes_hash(
221*d289c2baSAndroid Build Coastguard Worker ops->cert_ops, permanent_attributes_hash);
222*d289c2baSAndroid Build Coastguard Worker if (result != AVB_IO_RESULT_OK) {
223*d289c2baSAndroid Build Coastguard Worker avb_error("Failed to read permanent attributes hash.\n");
224*d289c2baSAndroid Build Coastguard Worker return result;
225*d289c2baSAndroid Build Coastguard Worker }
226*d289c2baSAndroid Build Coastguard Worker if (!verify_permanent_attributes(&permanent_attributes,
227*d289c2baSAndroid Build Coastguard Worker permanent_attributes_hash)) {
228*d289c2baSAndroid Build Coastguard Worker return AVB_IO_RESULT_OK;
229*d289c2baSAndroid Build Coastguard Worker }
230*d289c2baSAndroid Build Coastguard Worker
231*d289c2baSAndroid Build Coastguard Worker /* Sanity check public key metadata. */
232*d289c2baSAndroid Build Coastguard Worker if (public_key_metadata_length != sizeof(AvbCertPublicKeyMetadata)) {
233*d289c2baSAndroid Build Coastguard Worker avb_error("Invalid public key metadata.\n");
234*d289c2baSAndroid Build Coastguard Worker return AVB_IO_RESULT_OK;
235*d289c2baSAndroid Build Coastguard Worker }
236*d289c2baSAndroid Build Coastguard Worker avb_memcpy(&metadata, public_key_metadata, sizeof(AvbCertPublicKeyMetadata));
237*d289c2baSAndroid Build Coastguard Worker if (metadata.version != 1) {
238*d289c2baSAndroid Build Coastguard Worker avb_error("Unsupported public key metadata.\n");
239*d289c2baSAndroid Build Coastguard Worker return AVB_IO_RESULT_OK;
240*d289c2baSAndroid Build Coastguard Worker }
241*d289c2baSAndroid Build Coastguard Worker
242*d289c2baSAndroid Build Coastguard Worker /* Verify the PIK certificate. */
243*d289c2baSAndroid Build Coastguard Worker result = ops->read_rollback_index(
244*d289c2baSAndroid Build Coastguard Worker ops, AVB_CERT_PIK_VERSION_LOCATION, &minimum_version);
245*d289c2baSAndroid Build Coastguard Worker if (result != AVB_IO_RESULT_OK) {
246*d289c2baSAndroid Build Coastguard Worker avb_error("Failed to read PIK minimum version.\n");
247*d289c2baSAndroid Build Coastguard Worker return result;
248*d289c2baSAndroid Build Coastguard Worker }
249*d289c2baSAndroid Build Coastguard Worker if (!verify_pik_certificate(&metadata.product_intermediate_key_certificate,
250*d289c2baSAndroid Build Coastguard Worker permanent_attributes.product_root_public_key,
251*d289c2baSAndroid Build Coastguard Worker minimum_version)) {
252*d289c2baSAndroid Build Coastguard Worker return AVB_IO_RESULT_OK;
253*d289c2baSAndroid Build Coastguard Worker }
254*d289c2baSAndroid Build Coastguard Worker
255*d289c2baSAndroid Build Coastguard Worker /* Verify the PSK certificate. */
256*d289c2baSAndroid Build Coastguard Worker result = ops->read_rollback_index(
257*d289c2baSAndroid Build Coastguard Worker ops, AVB_CERT_PSK_VERSION_LOCATION, &minimum_version);
258*d289c2baSAndroid Build Coastguard Worker if (result != AVB_IO_RESULT_OK) {
259*d289c2baSAndroid Build Coastguard Worker avb_error("Failed to read PSK minimum version.\n");
260*d289c2baSAndroid Build Coastguard Worker return result;
261*d289c2baSAndroid Build Coastguard Worker }
262*d289c2baSAndroid Build Coastguard Worker if (!verify_psk_certificate(
263*d289c2baSAndroid Build Coastguard Worker &metadata.product_signing_key_certificate,
264*d289c2baSAndroid Build Coastguard Worker metadata.product_intermediate_key_certificate.signed_data.public_key,
265*d289c2baSAndroid Build Coastguard Worker minimum_version,
266*d289c2baSAndroid Build Coastguard Worker permanent_attributes.product_id)) {
267*d289c2baSAndroid Build Coastguard Worker return AVB_IO_RESULT_OK;
268*d289c2baSAndroid Build Coastguard Worker }
269*d289c2baSAndroid Build Coastguard Worker
270*d289c2baSAndroid Build Coastguard Worker /* Verify the PSK is the same key that verified vbmeta. */
271*d289c2baSAndroid Build Coastguard Worker if (public_key_length != AVB_CERT_PUBLIC_KEY_SIZE) {
272*d289c2baSAndroid Build Coastguard Worker avb_error("Public key length mismatch.\n");
273*d289c2baSAndroid Build Coastguard Worker return AVB_IO_RESULT_OK;
274*d289c2baSAndroid Build Coastguard Worker }
275*d289c2baSAndroid Build Coastguard Worker if (0 != avb_safe_memcmp(
276*d289c2baSAndroid Build Coastguard Worker metadata.product_signing_key_certificate.signed_data.public_key,
277*d289c2baSAndroid Build Coastguard Worker public_key_data,
278*d289c2baSAndroid Build Coastguard Worker AVB_CERT_PUBLIC_KEY_SIZE)) {
279*d289c2baSAndroid Build Coastguard Worker avb_error("Public key mismatch.\n");
280*d289c2baSAndroid Build Coastguard Worker return AVB_IO_RESULT_OK;
281*d289c2baSAndroid Build Coastguard Worker }
282*d289c2baSAndroid Build Coastguard Worker
283*d289c2baSAndroid Build Coastguard Worker /* Report the key versions used during verification. */
284*d289c2baSAndroid Build Coastguard Worker ops->cert_ops->set_key_version(
285*d289c2baSAndroid Build Coastguard Worker ops->cert_ops,
286*d289c2baSAndroid Build Coastguard Worker AVB_CERT_PIK_VERSION_LOCATION,
287*d289c2baSAndroid Build Coastguard Worker metadata.product_intermediate_key_certificate.signed_data.key_version);
288*d289c2baSAndroid Build Coastguard Worker ops->cert_ops->set_key_version(
289*d289c2baSAndroid Build Coastguard Worker ops->cert_ops,
290*d289c2baSAndroid Build Coastguard Worker AVB_CERT_PSK_VERSION_LOCATION,
291*d289c2baSAndroid Build Coastguard Worker metadata.product_signing_key_certificate.signed_data.key_version);
292*d289c2baSAndroid Build Coastguard Worker
293*d289c2baSAndroid Build Coastguard Worker *out_is_trusted = true;
294*d289c2baSAndroid Build Coastguard Worker return AVB_IO_RESULT_OK;
295*d289c2baSAndroid Build Coastguard Worker }
296*d289c2baSAndroid Build Coastguard Worker
avb_cert_generate_unlock_challenge(AvbCertOps * cert_ops,AvbCertUnlockChallenge * out_unlock_challenge)297*d289c2baSAndroid Build Coastguard Worker AvbIOResult avb_cert_generate_unlock_challenge(
298*d289c2baSAndroid Build Coastguard Worker AvbCertOps* cert_ops, AvbCertUnlockChallenge* out_unlock_challenge) {
299*d289c2baSAndroid Build Coastguard Worker AvbIOResult result = AVB_IO_RESULT_OK;
300*d289c2baSAndroid Build Coastguard Worker AvbCertPermanentAttributes permanent_attributes;
301*d289c2baSAndroid Build Coastguard Worker
302*d289c2baSAndroid Build Coastguard Worker /* We need the permanent attributes to compute the product_id_hash. */
303*d289c2baSAndroid Build Coastguard Worker result = cert_ops->read_permanent_attributes(cert_ops, &permanent_attributes);
304*d289c2baSAndroid Build Coastguard Worker if (result != AVB_IO_RESULT_OK) {
305*d289c2baSAndroid Build Coastguard Worker avb_error("Failed to read permanent attributes.\n");
306*d289c2baSAndroid Build Coastguard Worker return result;
307*d289c2baSAndroid Build Coastguard Worker }
308*d289c2baSAndroid Build Coastguard Worker result = cert_ops->get_random(
309*d289c2baSAndroid Build Coastguard Worker cert_ops, AVB_CERT_UNLOCK_CHALLENGE_SIZE, last_unlock_challenge);
310*d289c2baSAndroid Build Coastguard Worker if (result != AVB_IO_RESULT_OK) {
311*d289c2baSAndroid Build Coastguard Worker avb_error("Failed to generate random challenge.\n");
312*d289c2baSAndroid Build Coastguard Worker return result;
313*d289c2baSAndroid Build Coastguard Worker }
314*d289c2baSAndroid Build Coastguard Worker last_unlock_challenge_set = true;
315*d289c2baSAndroid Build Coastguard Worker out_unlock_challenge->version = 1;
316*d289c2baSAndroid Build Coastguard Worker sha256(permanent_attributes.product_id,
317*d289c2baSAndroid Build Coastguard Worker AVB_CERT_PRODUCT_ID_SIZE,
318*d289c2baSAndroid Build Coastguard Worker out_unlock_challenge->product_id_hash);
319*d289c2baSAndroid Build Coastguard Worker avb_memcpy(out_unlock_challenge->challenge,
320*d289c2baSAndroid Build Coastguard Worker last_unlock_challenge,
321*d289c2baSAndroid Build Coastguard Worker AVB_CERT_UNLOCK_CHALLENGE_SIZE);
322*d289c2baSAndroid Build Coastguard Worker return result;
323*d289c2baSAndroid Build Coastguard Worker }
324*d289c2baSAndroid Build Coastguard Worker
avb_cert_validate_unlock_credential(AvbCertOps * cert_ops,const AvbCertUnlockCredential * unlock_credential,bool * out_is_trusted)325*d289c2baSAndroid Build Coastguard Worker AvbIOResult avb_cert_validate_unlock_credential(
326*d289c2baSAndroid Build Coastguard Worker AvbCertOps* cert_ops,
327*d289c2baSAndroid Build Coastguard Worker const AvbCertUnlockCredential* unlock_credential,
328*d289c2baSAndroid Build Coastguard Worker bool* out_is_trusted) {
329*d289c2baSAndroid Build Coastguard Worker AvbIOResult result = AVB_IO_RESULT_OK;
330*d289c2baSAndroid Build Coastguard Worker AvbCertPermanentAttributes permanent_attributes;
331*d289c2baSAndroid Build Coastguard Worker uint8_t permanent_attributes_hash[AVB_SHA256_DIGEST_SIZE];
332*d289c2baSAndroid Build Coastguard Worker uint64_t minimum_version;
333*d289c2baSAndroid Build Coastguard Worker const AvbAlgorithmData* algorithm_data;
334*d289c2baSAndroid Build Coastguard Worker uint8_t challenge_hash[AVB_SHA512_DIGEST_SIZE];
335*d289c2baSAndroid Build Coastguard Worker
336*d289c2baSAndroid Build Coastguard Worker /* Be pessimistic so we can exit early without having to remember to clear.
337*d289c2baSAndroid Build Coastguard Worker */
338*d289c2baSAndroid Build Coastguard Worker *out_is_trusted = false;
339*d289c2baSAndroid Build Coastguard Worker
340*d289c2baSAndroid Build Coastguard Worker /* Sanity check the credential. */
341*d289c2baSAndroid Build Coastguard Worker if (unlock_credential->version != 1) {
342*d289c2baSAndroid Build Coastguard Worker avb_error("Unsupported unlock credential format.\n");
343*d289c2baSAndroid Build Coastguard Worker return AVB_IO_RESULT_OK;
344*d289c2baSAndroid Build Coastguard Worker }
345*d289c2baSAndroid Build Coastguard Worker
346*d289c2baSAndroid Build Coastguard Worker /* Read and verify permanent attributes. */
347*d289c2baSAndroid Build Coastguard Worker result = cert_ops->read_permanent_attributes(cert_ops, &permanent_attributes);
348*d289c2baSAndroid Build Coastguard Worker if (result != AVB_IO_RESULT_OK) {
349*d289c2baSAndroid Build Coastguard Worker avb_error("Failed to read permanent attributes.\n");
350*d289c2baSAndroid Build Coastguard Worker return result;
351*d289c2baSAndroid Build Coastguard Worker }
352*d289c2baSAndroid Build Coastguard Worker result = cert_ops->read_permanent_attributes_hash(cert_ops,
353*d289c2baSAndroid Build Coastguard Worker permanent_attributes_hash);
354*d289c2baSAndroid Build Coastguard Worker if (result != AVB_IO_RESULT_OK) {
355*d289c2baSAndroid Build Coastguard Worker avb_error("Failed to read permanent attributes hash.\n");
356*d289c2baSAndroid Build Coastguard Worker return result;
357*d289c2baSAndroid Build Coastguard Worker }
358*d289c2baSAndroid Build Coastguard Worker if (!verify_permanent_attributes(&permanent_attributes,
359*d289c2baSAndroid Build Coastguard Worker permanent_attributes_hash)) {
360*d289c2baSAndroid Build Coastguard Worker return AVB_IO_RESULT_OK;
361*d289c2baSAndroid Build Coastguard Worker }
362*d289c2baSAndroid Build Coastguard Worker
363*d289c2baSAndroid Build Coastguard Worker /* Verify the PIK certificate. */
364*d289c2baSAndroid Build Coastguard Worker result = cert_ops->ops->read_rollback_index(
365*d289c2baSAndroid Build Coastguard Worker cert_ops->ops, AVB_CERT_PIK_VERSION_LOCATION, &minimum_version);
366*d289c2baSAndroid Build Coastguard Worker if (result != AVB_IO_RESULT_OK) {
367*d289c2baSAndroid Build Coastguard Worker avb_error("Failed to read PIK minimum version.\n");
368*d289c2baSAndroid Build Coastguard Worker return result;
369*d289c2baSAndroid Build Coastguard Worker }
370*d289c2baSAndroid Build Coastguard Worker if (!verify_pik_certificate(
371*d289c2baSAndroid Build Coastguard Worker &unlock_credential->product_intermediate_key_certificate,
372*d289c2baSAndroid Build Coastguard Worker permanent_attributes.product_root_public_key,
373*d289c2baSAndroid Build Coastguard Worker minimum_version)) {
374*d289c2baSAndroid Build Coastguard Worker return AVB_IO_RESULT_OK;
375*d289c2baSAndroid Build Coastguard Worker }
376*d289c2baSAndroid Build Coastguard Worker
377*d289c2baSAndroid Build Coastguard Worker /* Verify the PUK certificate. The minimum version is shared with the PSK. */
378*d289c2baSAndroid Build Coastguard Worker result = cert_ops->ops->read_rollback_index(
379*d289c2baSAndroid Build Coastguard Worker cert_ops->ops, AVB_CERT_PSK_VERSION_LOCATION, &minimum_version);
380*d289c2baSAndroid Build Coastguard Worker if (result != AVB_IO_RESULT_OK) {
381*d289c2baSAndroid Build Coastguard Worker avb_error("Failed to read PSK minimum version.\n");
382*d289c2baSAndroid Build Coastguard Worker return result;
383*d289c2baSAndroid Build Coastguard Worker }
384*d289c2baSAndroid Build Coastguard Worker if (!verify_puk_certificate(
385*d289c2baSAndroid Build Coastguard Worker &unlock_credential->product_unlock_key_certificate,
386*d289c2baSAndroid Build Coastguard Worker unlock_credential->product_intermediate_key_certificate.signed_data
387*d289c2baSAndroid Build Coastguard Worker .public_key,
388*d289c2baSAndroid Build Coastguard Worker minimum_version,
389*d289c2baSAndroid Build Coastguard Worker permanent_attributes.product_id)) {
390*d289c2baSAndroid Build Coastguard Worker return AVB_IO_RESULT_OK;
391*d289c2baSAndroid Build Coastguard Worker }
392*d289c2baSAndroid Build Coastguard Worker
393*d289c2baSAndroid Build Coastguard Worker /* Hash the most recent unlock challenge. */
394*d289c2baSAndroid Build Coastguard Worker if (!last_unlock_challenge_set) {
395*d289c2baSAndroid Build Coastguard Worker avb_error("Challenge does not exist.\n");
396*d289c2baSAndroid Build Coastguard Worker return AVB_IO_RESULT_OK;
397*d289c2baSAndroid Build Coastguard Worker }
398*d289c2baSAndroid Build Coastguard Worker sha512(last_unlock_challenge, AVB_CERT_UNLOCK_CHALLENGE_SIZE, challenge_hash);
399*d289c2baSAndroid Build Coastguard Worker last_unlock_challenge_set = false;
400*d289c2baSAndroid Build Coastguard Worker
401*d289c2baSAndroid Build Coastguard Worker /* Verify the challenge signature. */
402*d289c2baSAndroid Build Coastguard Worker algorithm_data = avb_get_algorithm_data(AVB_ALGORITHM_TYPE_SHA512_RSA4096);
403*d289c2baSAndroid Build Coastguard Worker if (!avb_rsa_verify(unlock_credential->product_unlock_key_certificate
404*d289c2baSAndroid Build Coastguard Worker .signed_data.public_key,
405*d289c2baSAndroid Build Coastguard Worker AVB_CERT_PUBLIC_KEY_SIZE,
406*d289c2baSAndroid Build Coastguard Worker unlock_credential->challenge_signature,
407*d289c2baSAndroid Build Coastguard Worker AVB_RSA4096_NUM_BYTES,
408*d289c2baSAndroid Build Coastguard Worker challenge_hash,
409*d289c2baSAndroid Build Coastguard Worker AVB_SHA512_DIGEST_SIZE,
410*d289c2baSAndroid Build Coastguard Worker algorithm_data->padding,
411*d289c2baSAndroid Build Coastguard Worker algorithm_data->padding_len)) {
412*d289c2baSAndroid Build Coastguard Worker avb_error("Invalid unlock challenge signature.\n");
413*d289c2baSAndroid Build Coastguard Worker return AVB_IO_RESULT_OK;
414*d289c2baSAndroid Build Coastguard Worker }
415*d289c2baSAndroid Build Coastguard Worker
416*d289c2baSAndroid Build Coastguard Worker *out_is_trusted = true;
417*d289c2baSAndroid Build Coastguard Worker return AVB_IO_RESULT_OK;
418*d289c2baSAndroid Build Coastguard Worker }
419