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