blob: 1db57cc74d443be52cb467b39e554de02f620470 [file] [log] [blame]
Amit Blay6281ebc2015-01-11 14:44:08 +02001/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <debug.h>
30#include <dev/fbcon.h>
31#include <target.h>
32#include <mmc.h>
33#include <partition_parser.h>
34#include <platform.h>
35#include <crypto_hash.h>
36#include <malloc.h>
37#include <sha.h>
38#include <string.h>
39#include <rand.h>
40#include <stdlib.h>
Amit Blay4aa292f2015-04-28 21:55:59 +030041#include <boot_verifier.h>
42#include <image_verify.h>
Amit Blay6281ebc2015-01-11 14:44:08 +020043#include "scm.h"
44#include "mdtp.h"
45
Amit Blay4aa292f2015-04-28 21:55:59 +030046#define DIP_ENCRYPT (0)
47#define DIP_DECRYPT (1)
48#define MAX_CIPHER_DIP_SCM_CALLS (3)
Amit Blay6281ebc2015-01-11 14:44:08 +020049
Amit Blay8e2731c2015-04-28 21:54:55 +030050#define MDTP_MAJOR_VERSION (0)
51#define MDTP_MINOR_VERSION (2)
52
53/** Extract major version number from complete version. */
54#define MDTP_GET_MAJOR_VERSION(version) ((version) >> 16)
55
Amit Blaydf42d2f2015-02-03 16:37:09 +020056static int mdtp_tzbsp_dec_verify_DIP(DIP_t *enc_dip, DIP_t *dec_dip, uint32_t *verified);
57static int mdtp_tzbsp_enc_hash_DIP(DIP_t *dec_dip, DIP_t *enc_dip);
Amit Blay4aa292f2015-04-28 21:55:59 +030058static void mdtp_tzbsp_disallow_cipher_DIP(void);
Amit Blay6281ebc2015-01-11 14:44:08 +020059
Amit Blay8e2731c2015-04-28 21:54:55 +030060uint32_t g_mdtp_version = (((MDTP_MAJOR_VERSION << 16) & 0xFFFF0000) | (MDTP_MINOR_VERSION & 0x0000FFFF));
Amit Blay4aa292f2015-04-28 21:55:59 +030061static int is_mdtp_activated = -1;
Amit Blay8e2731c2015-04-28 21:54:55 +030062
Amit Blay8e2731c2015-04-28 21:54:55 +030063int check_aboot_addr_range_overlap(uint32_t start, uint32_t size);
Amit Blay4aa292f2015-04-28 21:55:59 +030064int scm_random(uint32_t * rbuf, uint32_t r_len);
Amit Blay8e2731c2015-04-28 21:54:55 +030065
Amit Blay6281ebc2015-01-11 14:44:08 +020066/********************************************************************************/
67
68/* Read the DIP from EMMC */
Amit Blaydf42d2f2015-02-03 16:37:09 +020069static int read_DIP(DIP_t *dip)
Amit Blay6281ebc2015-01-11 14:44:08 +020070{
71 unsigned long long ptn = 0;
72 uint32_t actual_partition_size;
Amit Blaydf42d2f2015-02-03 16:37:09 +020073 uint32_t block_size = mmc_get_device_blocksize();
Amit Blay6281ebc2015-01-11 14:44:08 +020074
75 int index = INVALID_PTN;
76
77 ASSERT(dip != NULL);
78
79 index = partition_get_index("dip");
80 ptn = partition_get_offset(index);
81
82 if(ptn == 0)
83 {
84 return -1;
85 }
86
87 actual_partition_size = ROUNDUP(sizeof(DIP_t), block_size);
88
89 if(mmc_read(ptn, (void *)dip, actual_partition_size))
90 {
91 dprintf(CRITICAL, "mdtp: read_DIP: ERROR, cannot read DIP info\n");
92 return -1;
93 }
94
Reut Zysman18411272015-02-09 13:47:27 +020095 dprintf(SPEW, "mdtp: read_DIP: SUCCESS, read %d bytes\n", actual_partition_size);
Amit Blay6281ebc2015-01-11 14:44:08 +020096
97 return 0;
98}
99
100/* Store the DIP into the EMMC */
Amit Blaydf42d2f2015-02-03 16:37:09 +0200101static int write_DIP(DIP_t *dip)
Amit Blay6281ebc2015-01-11 14:44:08 +0200102{
103 unsigned long long ptn = 0;
Amit Blaydf42d2f2015-02-03 16:37:09 +0200104 uint32_t block_size = mmc_get_device_blocksize();
Amit Blay6281ebc2015-01-11 14:44:08 +0200105
106 int index = INVALID_PTN;
107
108 ASSERT(dip != NULL);
109
110 index = partition_get_index("dip");
111 ptn = partition_get_offset(index);
Reut Zysman18411272015-02-09 13:47:27 +0200112
Amit Blay6281ebc2015-01-11 14:44:08 +0200113 if(ptn == 0)
114 {
115 return -1;
116 }
117
Reut Zysman18411272015-02-09 13:47:27 +0200118 if(mmc_write(ptn, ROUNDUP(sizeof(DIP_t), block_size), (void *)dip))
Amit Blay6281ebc2015-01-11 14:44:08 +0200119 {
Amit Blay8e2731c2015-04-28 21:54:55 +0300120 dprintf(CRITICAL, "mdtp: write_DIP: ERROR, cannot write DIP info\n");
Amit Blay6281ebc2015-01-11 14:44:08 +0200121 return -1;
122 }
123
Reut Zysman18411272015-02-09 13:47:27 +0200124 dprintf(SPEW, "mdtp: write_DIP: SUCCESS, write %d bytes\n", ROUNDUP(sizeof(DIP_t), block_size));
125
Amit Blay6281ebc2015-01-11 14:44:08 +0200126 return 0;
127}
128
Reut Zysman18411272015-02-09 13:47:27 +0200129/* Deactivate MDTP by storing the default DIP into the EMMC */
130static void write_deactivated_DIP()
Amit Blay6281ebc2015-01-11 14:44:08 +0200131{
Amit Blaydf42d2f2015-02-03 16:37:09 +0200132 DIP_t *enc_dip;
133 DIP_t *dec_dip;
Amit Blay6281ebc2015-01-11 14:44:08 +0200134 int ret;
135
136 enc_dip = malloc(sizeof(DIP_t));
137 if (enc_dip == NULL)
138 {
Reut Zysman18411272015-02-09 13:47:27 +0200139 dprintf(CRITICAL, "mdtp: write_deactivated_DIP: ERROR, cannot allocate DIP\n");
Amit Blay6281ebc2015-01-11 14:44:08 +0200140 return;
141 }
142
143 dec_dip = malloc(sizeof(DIP_t));
144 if (dec_dip == NULL)
145 {
Reut Zysman18411272015-02-09 13:47:27 +0200146 dprintf(CRITICAL, "mdtp: write_deactivated_DIP: ERROR, cannot allocate DIP\n");
Amit Blay6281ebc2015-01-11 14:44:08 +0200147 free(enc_dip);
148 return;
149 }
150
151 memset(dec_dip, 0, sizeof(DIP_t));
152
153 dec_dip->status = DIP_STATUS_DEACTIVATED;
Amit Blay8e2731c2015-04-28 21:54:55 +0300154 dec_dip->version = g_mdtp_version;
Amit Blay6281ebc2015-01-11 14:44:08 +0200155
156 ret = mdtp_tzbsp_enc_hash_DIP(dec_dip, enc_dip);
157 if(ret < 0)
158 {
Reut Zysman18411272015-02-09 13:47:27 +0200159 dprintf(CRITICAL, "mdtp: write_deactivated_DIP: ERROR, cannot cipher DIP\n");
Amit Blay6281ebc2015-01-11 14:44:08 +0200160 goto out;
161 }
162
163 ret = write_DIP(enc_dip);
164 if(ret < 0)
165 {
Reut Zysman18411272015-02-09 13:47:27 +0200166 dprintf(CRITICAL, "mdtp: write_deactivated_DIP: ERROR, cannot write DIP\n");
Amit Blay6281ebc2015-01-11 14:44:08 +0200167 goto out;
168 }
169
170out:
171 free(enc_dip);
172 free(dec_dip);
173}
174
175/* Validate a hash calculated on entire given partition */
Amit Blay8e2731c2015-04-28 21:54:55 +0300176static int verify_partition_single_hash(char *name, uint64_t size, DIP_hash_table_entry_t *hash_table)
Amit Blay6281ebc2015-01-11 14:44:08 +0200177{
Amit Blay8e2731c2015-04-28 21:54:55 +0300178 unsigned char digest[HASH_LEN]={0};
Amit Blay6281ebc2015-01-11 14:44:08 +0200179 unsigned long long ptn = 0;
180 int index = INVALID_PTN;
Amit Blay4aa292f2015-04-28 21:55:59 +0300181 unsigned char *buf = (unsigned char *)target_get_scratch_address() + MDTP_SCRATCH_OFFSET;
Amit Blaydf42d2f2015-02-03 16:37:09 +0200182 uint32_t block_size = mmc_get_device_blocksize();
Amit Blay8e2731c2015-04-28 21:54:55 +0300183 uint64_t actual_partition_size = ROUNDUP(size, block_size);
Amit Blay6281ebc2015-01-11 14:44:08 +0200184
Amit Blay8e2731c2015-04-28 21:54:55 +0300185 dprintf(SPEW, "mdtp: verify_partition_single_hash: %s, %llu\n", name, size);
Amit Blay6281ebc2015-01-11 14:44:08 +0200186
187 ASSERT(name != NULL);
188 ASSERT(hash_table != NULL);
Amit Blay8e2731c2015-04-28 21:54:55 +0300189 ASSERT(size > 0);
Amit Blay6281ebc2015-01-11 14:44:08 +0200190
191 index = partition_get_index(name);
192 ptn = partition_get_offset(index);
193
194 if(ptn == 0) {
195 dprintf(CRITICAL, "mdtp: verify_partition_single_hash: %s: partition was not found\n", name);
196 return -1;
197 }
198
Amit Blay6281ebc2015-01-11 14:44:08 +0200199 if (mmc_read(ptn, (void *)buf, actual_partition_size))
200 {
Amit Blay8e2731c2015-04-28 21:54:55 +0300201 dprintf(CRITICAL, "mdtp: verify_partition_single_hash: %s: mmc_read() fail.\n", name);
Amit Blay6281ebc2015-01-11 14:44:08 +0200202 return -1;
203 }
204
Amit Blayfe649212015-01-25 11:21:10 +0200205 /* calculating the hash value using HW crypto */
206 target_crypto_init_params();
Amit Blay8e2731c2015-04-28 21:54:55 +0300207 hash_find(buf, size, digest, CRYPTO_AUTH_ALG_SHA256);
Amit Blay6281ebc2015-01-11 14:44:08 +0200208
Amit Blay8e2731c2015-04-28 21:54:55 +0300209 if (memcmp(digest, hash_table->hash, HASH_LEN))
Amit Blay6281ebc2015-01-11 14:44:08 +0200210 {
211 dprintf(CRITICAL, "mdtp: verify_partition_single_hash: %s: Failed partition hash verification\n", name);
212
213 return -1;
214 }
215
Reut Zysman18411272015-02-09 13:47:27 +0200216 dprintf(SPEW, "verify_partition_single_hash: %s: VERIFIED!\n", name);
Amit Blay6281ebc2015-01-11 14:44:08 +0200217
218 return 0;
219}
220
221/* Validate a hash table calculated per block of a given partition */
Amit Blaydf42d2f2015-02-03 16:37:09 +0200222static int verify_partition_block_hash(char *name,
Amit Blay8e2731c2015-04-28 21:54:55 +0300223 uint64_t size,
Amit Blay6281ebc2015-01-11 14:44:08 +0200224 uint32_t verify_num_blocks,
Amit Blaydf42d2f2015-02-03 16:37:09 +0200225 DIP_hash_table_entry_t *hash_table,
Amit Blay8e2731c2015-04-28 21:54:55 +0300226 uint8_t *force_verify_block)
Amit Blay6281ebc2015-01-11 14:44:08 +0200227{
Amit Blay8e2731c2015-04-28 21:54:55 +0300228 unsigned char digest[HASH_LEN]={0};
Amit Blay6281ebc2015-01-11 14:44:08 +0200229 unsigned long long ptn = 0;
230 int index = INVALID_PTN;
Amit Blay4aa292f2015-04-28 21:55:59 +0300231 unsigned char *buf = (unsigned char *)target_get_scratch_address() + MDTP_SCRATCH_OFFSET;
Amit Blay6281ebc2015-01-11 14:44:08 +0200232 uint32_t bytes_to_read;
233 uint32_t block_num = 0;
Amit Blay8e2731c2015-04-28 21:54:55 +0300234 uint32_t total_num_blocks = ((size - 1) / MDTP_FWLOCK_BLOCK_SIZE) + 1;
235 uint32_t rand_int;
236 uint32_t block_size = mmc_get_device_blocksize();
Amit Blay6281ebc2015-01-11 14:44:08 +0200237
Amit Blay8e2731c2015-04-28 21:54:55 +0300238 dprintf(SPEW, "mdtp: verify_partition_block_hash: %s, %llu\n", name, size);
Amit Blay6281ebc2015-01-11 14:44:08 +0200239
240 ASSERT(name != NULL);
241 ASSERT(hash_table != NULL);
Amit Blay8e2731c2015-04-28 21:54:55 +0300242 ASSERT(size > 0);
243 ASSERT(force_verify_block != NULL);
Amit Blay6281ebc2015-01-11 14:44:08 +0200244
245 index = partition_get_index(name);
246 ptn = partition_get_offset(index);
247
248 if(ptn == 0) {
249 dprintf(CRITICAL, "mdtp: verify_partition_block_hash: %s: partition was not found\n", name);
250 return -1;
251 }
252
Amit Blayfe649212015-01-25 11:21:10 +0200253 /* initiating parameters for hash calculation using HW crypto */
254 target_crypto_init_params();
Amit Blay8e2731c2015-04-28 21:54:55 +0300255 if (check_aboot_addr_range_overlap((uint32_t)buf, ROUNDUP(MDTP_FWLOCK_BLOCK_SIZE, block_size)))
256 {
257 dprintf(CRITICAL, "mdtp: verify_partition_block_hash: %s: image buffer address overlaps with aboot addresses.\n", name);
258 return -1;
259 }
Amit Blayfe649212015-01-25 11:21:10 +0200260
Amit Blay6281ebc2015-01-11 14:44:08 +0200261 while (MDTP_FWLOCK_BLOCK_SIZE * block_num < size)
262 {
263 if (*force_verify_block == 0)
264 {
Amit Blay8e2731c2015-04-28 21:54:55 +0300265 if(scm_random((uint32_t *)&rand_int, sizeof(rand_int)))
266 {
267 dprintf(CRITICAL,"mdtp: scm_call for random failed\n");
268 return -1;
269 }
270
Amit Blay6281ebc2015-01-11 14:44:08 +0200271 /* Skip validation of this block with probability of verify_num_blocks / total_num_blocks */
Amit Blay8e2731c2015-04-28 21:54:55 +0300272 if ((rand_int % total_num_blocks) >= verify_num_blocks)
Amit Blay6281ebc2015-01-11 14:44:08 +0200273 {
274 block_num++;
275 hash_table += 1;
276 force_verify_block += 1;
277 dprintf(CRITICAL, "mdtp: verify_partition_block_hash: %s: skipped verification of block %d\n", name, block_num);
278 continue;
279 }
280 }
281
Amit Blay6281ebc2015-01-11 14:44:08 +0200282 if ((size - (MDTP_FWLOCK_BLOCK_SIZE * block_num) < MDTP_FWLOCK_BLOCK_SIZE))
283 {
284 bytes_to_read = size - (MDTP_FWLOCK_BLOCK_SIZE * block_num);
285 } else
286 {
287 bytes_to_read = MDTP_FWLOCK_BLOCK_SIZE;
288 }
289
Amit Blay8e2731c2015-04-28 21:54:55 +0300290 if (mmc_read(ptn + (MDTP_FWLOCK_BLOCK_SIZE * block_num), (void *)buf, ROUNDUP(bytes_to_read, block_size)))
Amit Blay6281ebc2015-01-11 14:44:08 +0200291 {
292 dprintf(CRITICAL, "mdtp: verify_partition_block_hash: %s: mmc_read() fail.\n", name);
293 return -1;
294 }
295
Amit Blayfe649212015-01-25 11:21:10 +0200296 /* calculating the hash value using HW */
Amit Blay8e2731c2015-04-28 21:54:55 +0300297 hash_find(buf, bytes_to_read, digest, CRYPTO_AUTH_ALG_SHA256);
Amit Blay6281ebc2015-01-11 14:44:08 +0200298
Amit Blay8e2731c2015-04-28 21:54:55 +0300299 if (memcmp(digest, hash_table->hash, HASH_LEN))
Amit Blay6281ebc2015-01-11 14:44:08 +0200300 {
301 dprintf(CRITICAL, "mdtp: verify_partition_block_hash: %s: Failed partition hash[%d] verification\n", name, block_num);
302 return -1;
303 }
304
305 block_num++;
306 hash_table += 1;
307 force_verify_block += 1;
308 }
309
Reut Zysman18411272015-02-09 13:47:27 +0200310 dprintf(SPEW, "verify_partition_block_hash: %s: VERIFIED!\n", name);
Amit Blay6281ebc2015-01-11 14:44:08 +0200311
312 return 0;
313}
314
Amit Blay8e2731c2015-04-28 21:54:55 +0300315/* Validate the partition parameters read from DIP */
316static int validate_partition_params(uint64_t size,
Amit Blay6281ebc2015-01-11 14:44:08 +0200317 mdtp_fwlock_mode_t hash_mode,
Amit Blay8e2731c2015-04-28 21:54:55 +0300318 uint32_t verify_ratio)
Amit Blay6281ebc2015-01-11 14:44:08 +0200319{
Amit Blay8e2731c2015-04-28 21:54:55 +0300320 if (size == 0 || size > (uint64_t)MDTP_FWLOCK_BLOCK_SIZE * (uint64_t)MAX_BLOCKS ||
321 hash_mode >= MDTP_FWLOCK_MODE_SIZE || verify_ratio > 100)
Amit Blay6281ebc2015-01-11 14:44:08 +0200322 {
Amit Blay8e2731c2015-04-28 21:54:55 +0300323 dprintf(CRITICAL, "mdtp: validate_partition_params: error, size=%llu, hash_mode=%d, verify_ratio=%d\n",
324 size, hash_mode, verify_ratio);
Amit Blay6281ebc2015-01-11 14:44:08 +0200325 return -1;
326 }
327
328 return 0;
329}
330
Amit Blay8e2731c2015-04-28 21:54:55 +0300331/* Verify a given partitinon */
332static int verify_partition(char *name,
333 uint64_t size,
334 mdtp_fwlock_mode_t hash_mode,
335 uint32_t verify_num_blocks,
336 DIP_hash_table_entry_t *hash_table,
337 uint8_t *force_verify_block)
338{
339 if (hash_mode == MDTP_FWLOCK_MODE_SINGLE)
340 {
341 return verify_partition_single_hash(name, size, hash_table);
342 } else if (hash_mode == MDTP_FWLOCK_MODE_BLOCK || hash_mode == MDTP_FWLOCK_MODE_FILES)
343 {
344 return verify_partition_block_hash(name, size, verify_num_blocks, hash_table, force_verify_block);
345 }
346
347 /* Illegal value of hash_mode */
348 return -1;
349}
350
351static int validate_dip(DIP_t *dip)
352{
353 uint8_t *dip_p;
354
355 ASSERT(dip != NULL);
356
357 /* Make sure DIP version is supported by current SW */
358 if (MDTP_GET_MAJOR_VERSION(dip->version) != MDTP_MAJOR_VERSION)
359 {
360 dprintf(CRITICAL, "mdtp: validate_dip: Wrong DIP version 0x%x\n", dip->version);
361 return -1;
362 }
363
364 /* Make sure that deactivated DIP content is as expected */
365 if (dip->status == DIP_STATUS_DEACTIVATED)
366 {
367 dip_p = (uint8_t*)&dip->mdtp_cfg;
368 while (dip_p < dip->hash)
369 {
370 if (*dip_p != 0)
371 {
372 dprintf(CRITICAL, "mdtp: validate_dip: error in deactivated DIP\n");
373 return -1;
374 }
375 dip_p++;
376 }
377 }
378
379 return 0;
380}
381
Reut Zysman18411272015-02-09 13:47:27 +0200382/* Display the recovery UI to allow the user to enter the PIN and continue boot */
Amit Blay4aa292f2015-04-28 21:55:59 +0300383static void display_recovery_ui(mdtp_cfg_t *mdtp_cfg)
Reut Zysman18411272015-02-09 13:47:27 +0200384{
385 uint32_t pin_length = 0;
386 char entered_pin[MDTP_MAX_PIN_LEN+1] = {0};
387 uint32_t i;
Amit Blay8e2731c2015-04-28 21:54:55 +0300388 char pin_mismatch = 0;
Reut Zysman18411272015-02-09 13:47:27 +0200389
Amit Blay4aa292f2015-04-28 21:55:59 +0300390 if (mdtp_cfg->enable_local_pin_authentication)
Reut Zysman18411272015-02-09 13:47:27 +0200391 {
392 dprintf(SPEW, "mdtp: display_recovery_ui: Local deactivation enabled\n");
393
Amit Blay4aa292f2015-04-28 21:55:59 +0300394 pin_length = strlen(mdtp_cfg->mdtp_pin.mdtp_pin);
Reut Zysman18411272015-02-09 13:47:27 +0200395
396 if (pin_length > MDTP_MAX_PIN_LEN || pin_length < MDTP_MIN_PIN_LEN)
397 {
398 dprintf(CRITICAL, "mdtp: display_recovery_ui: Error, invalid PIN length\n");
Amit Blay8e2731c2015-04-28 21:54:55 +0300399 display_error_msg(); /* This will never return */
Reut Zysman18411272015-02-09 13:47:27 +0200400 }
401
402 // Set entered_pin to initial '0' string + null terminator
403 for (i=0; i<pin_length; i++)
404 {
405 entered_pin[i] = '0';
406 }
407
408 // Allow the user to enter the PIN as many times as he wishes
409 // (with INVALID_PIN_DELAY_MSECONDS after each failed attempt)
410 while (1)
411 {
Amit Blay8e2731c2015-04-28 21:54:55 +0300412 get_pin_from_user(entered_pin, pin_length);
Reut Zysman18411272015-02-09 13:47:27 +0200413
Amit Blay8e2731c2015-04-28 21:54:55 +0300414 // Go over the entire PIN in any case, to prevent side-channel attacks
415 for (i=0; i<pin_length; i++)
416 {
Amit Blay4aa292f2015-04-28 21:55:59 +0300417 pin_mismatch |= mdtp_cfg->mdtp_pin.mdtp_pin[i] ^ entered_pin[i];
Amit Blay8e2731c2015-04-28 21:54:55 +0300418 }
Reut Zysman18411272015-02-09 13:47:27 +0200419
Amit Blay8e2731c2015-04-28 21:54:55 +0300420 if (0 == pin_mismatch)
421 {
422 // Valid PIN - deactivate and continue boot
423 dprintf(SPEW, "mdtp: display_recovery_ui: valid PIN, continue boot\n");
424 write_deactivated_DIP();
425 return;
426 }
427 else
428 {
429 // Invalid PIN - display an appropriate message (which also includes a wait
430 // for INVALID_PIN_DELAY_MSECONDS), and allow the user to try again
431 dprintf(CRITICAL, "mdtp: display_recovery_ui: ERROR, invalid PIN\n");
432 display_invalid_pin_msg();
Reut Zysman18411272015-02-09 13:47:27 +0200433
Amit Blay8e2731c2015-04-28 21:54:55 +0300434 pin_mismatch = 0;
435 }
Reut Zysman18411272015-02-09 13:47:27 +0200436 }
437 }
438 else
439 {
440 dprintf(CRITICAL, "mdtp: display_recovery_ui: Local deactivation disabled, unable to display recovery UI\n");
Amit Blay8e2731c2015-04-28 21:54:55 +0300441 display_error_msg(); /* This will never return */
Reut Zysman18411272015-02-09 13:47:27 +0200442 }
443}
444
Amit Blay4aa292f2015-04-28 21:55:59 +0300445/* Verify the boot or recovery partitions using boot_verifier. */
446static int verify_ext_partition(mdtp_ext_partition_verification_t *ext_partition)
447{
448 int ret = 0;
449 bool restore_to_orange = false;
450 unsigned long long ptn = 0;
451 int index = INVALID_PTN;
452
453 /* If image was already verified in aboot, return its status */
454 if (ext_partition->integrity_state == MDTP_PARTITION_STATE_INVALID)
455 {
456 dprintf(CRITICAL, "mdtp: verify_ext_partition: image %s verified externally and failed.\n",
457 ext_partition->partition == MDTP_PARTITION_BOOT ? "boot" : "recovery");
458 return -1;
459 }
460 else if (ext_partition->integrity_state == MDTP_PARTITION_STATE_VALID)
461 {
462 dprintf(CRITICAL, "mdtp: verify_ext_partition: image %s verified externally succesfully.\n",
463 ext_partition->partition == MDTP_PARTITION_BOOT ? "boot" : "recovery");
464 return 0;
465 }
466
467 /* If image was not verified in aboot, verify it ourselves using boot_verifier. */
468
469 /* 1) Initialize keystore. We don't care about return value which is Verified Boot's state machine state. */
470 boot_verify_keystore_init();
471
472 /* 2) If boot_verifier is ORANGE, it will prevent verifying an image. So
473 * temporarly change boot_verifier state to BOOT_INIT.
474 */
475 if (boot_verify_get_state() == ORANGE)
476 restore_to_orange = true;
477 boot_verify_send_event(BOOT_INIT);
478
479 switch (ext_partition->partition)
480 {
481 case MDTP_PARTITION_BOOT:
482 case MDTP_PARTITION_RECOVERY:
483
484 /* 3) Signature may or may not be at the end of the image. Read the signature if needed. */
485 if (!ext_partition->sig_avail)
486 {
487 if (check_aboot_addr_range_overlap((uint32_t)(ext_partition->image_addr + ext_partition->image_size), ext_partition->page_size))
488 {
489 dprintf(CRITICAL, "ERROR: Signature read buffer address overlaps with aboot addresses.\n");
490 return -1;
491 }
492
493 index = partition_get_index(ext_partition->partition == MDTP_PARTITION_BOOT ? "boot" : "recovery");
494 ptn = partition_get_offset(index);
495 if(ptn == 0) {
496 dprintf(CRITICAL, "ERROR: partition %s not found\n",
497 ext_partition->partition == MDTP_PARTITION_BOOT ? "boot" : "recovery");
498 return -1;
499 }
500
501 if(mmc_read(ptn + ext_partition->image_size, (void *)(ext_partition->image_addr + ext_partition->image_size), ext_partition->page_size))
502 {
503 dprintf(CRITICAL, "ERROR: Cannot read %s image signature\n",
504 ext_partition->partition == MDTP_PARTITION_BOOT ? "boot" : "recovery");
505 return -1;
506 }
507 }
508
509 /* 4) Verify the image using its signature. */
510 ret = boot_verify_image((unsigned char *)ext_partition->image_addr,
511 ext_partition->image_size,
512 ext_partition->partition == MDTP_PARTITION_BOOT ? "boot" : "recovery");
513 break;
514
515 default:
516 /* Only boot and recovery are legal here */
517 dprintf(CRITICAL, "ERROR: wrong partition %d\n", ext_partition->partition);
518 return -1;
519 }
520
521 if (ret)
522 {
523 dprintf(INFO, "mdtp: verify_ext_partition: image %s verified succesfully in MDTP.\n",
524 ext_partition->partition == MDTP_PARTITION_BOOT ? "boot" : "recovery");
525 }
526 else
527 {
528 dprintf(CRITICAL, "mdtp: verify_ext_partition: image %s verification failed in MDTP.\n",
529 ext_partition->partition == MDTP_PARTITION_BOOT ? "boot" : "recovery");
530 }
531
532 /* 5) Restore the right boot_verifier state upon exit. */
533 if (restore_to_orange)
534 {
535 boot_verify_send_event(DEV_UNLOCK);
536 }
537
538 return ret ? 0 : -1;
539}
540
Amit Blay6281ebc2015-01-11 14:44:08 +0200541/* Verify all protected partitinons according to the DIP */
Amit Blay4aa292f2015-04-28 21:55:59 +0300542static void verify_all_partitions(DIP_t *dip,
543 mdtp_ext_partition_verification_t *ext_partition,
544 verify_result_t *verify_result)
Amit Blay6281ebc2015-01-11 14:44:08 +0200545{
546 int i;
Amit Blay4aa292f2015-04-28 21:55:59 +0300547 int verify_failure = 0;
548 int ext_partition_verify_failure = 0;
Amit Blay6281ebc2015-01-11 14:44:08 +0200549 uint32_t total_num_blocks;
550
551 ASSERT(dip != NULL);
552 ASSERT(verify_result != NULL);
553
554 *verify_result = VERIFY_FAILED;
555
Amit Blay8e2731c2015-04-28 21:54:55 +0300556 if (validate_dip(dip))
557 {
558 dprintf(CRITICAL, "mdtp: verify_all_partitions: failed DIP validation\n");
559 return;
560 }
561
Amit Blay6281ebc2015-01-11 14:44:08 +0200562 if (dip->status == DIP_STATUS_DEACTIVATED)
563 {
564 *verify_result = VERIFY_SKIPPED;
Amit Blay8e2731c2015-04-28 21:54:55 +0300565 return;
Amit Blay6281ebc2015-01-11 14:44:08 +0200566 }
Amit Blay8e2731c2015-04-28 21:54:55 +0300567 else
Amit Blay6281ebc2015-01-11 14:44:08 +0200568 {
Amit Blay6281ebc2015-01-11 14:44:08 +0200569 for(i=0; i<MAX_PARTITIONS; i++)
570 {
571 if(dip->partition_cfg[i].lock_enabled && dip->partition_cfg[i].size)
572 {
573 total_num_blocks = ((dip->partition_cfg[i].size - 1) / MDTP_FWLOCK_BLOCK_SIZE);
Amit Blay8e2731c2015-04-28 21:54:55 +0300574 if (validate_partition_params(dip->partition_cfg[i].size,
575 dip->partition_cfg[i].hash_mode,
576 dip->partition_cfg[i].verify_ratio))
577 {
578 dprintf(CRITICAL, "mdtp: verify_all_partitions: Wrong partition parameters\n");
579 verify_failure = TRUE;
580 break;
581 }
Amit Blay6281ebc2015-01-11 14:44:08 +0200582
Amit Blay8e2731c2015-04-28 21:54:55 +0300583 verify_failure |= (verify_partition(dip->partition_cfg[i].name,
Amit Blay6281ebc2015-01-11 14:44:08 +0200584 dip->partition_cfg[i].size,
585 dip->partition_cfg[i].hash_mode,
Amit Blay6281ebc2015-01-11 14:44:08 +0200586 (dip->partition_cfg[i].verify_ratio * total_num_blocks) / 100,
587 dip->partition_cfg[i].hash_table,
Amit Blay8e2731c2015-04-28 21:54:55 +0300588 dip->partition_cfg[i].force_verify_block) != 0);
Amit Blay6281ebc2015-01-11 14:44:08 +0200589 }
590 }
591
Amit Blay4aa292f2015-04-28 21:55:59 +0300592 ext_partition_verify_failure = verify_ext_partition(ext_partition);
593
594 if (verify_failure || ext_partition_verify_failure)
Amit Blay6281ebc2015-01-11 14:44:08 +0200595 {
596 dprintf(CRITICAL, "mdtp: verify_all_partitions: Failed partition verification\n");
Amit Blay8e2731c2015-04-28 21:54:55 +0300597 return;
Amit Blay6281ebc2015-01-11 14:44:08 +0200598 }
Shay Nachmanibc10dfe2015-02-10 14:45:55 +0200599 is_mdtp_activated = 1;
Amit Blay6281ebc2015-01-11 14:44:08 +0200600
601 }
602
603 *verify_result = VERIFY_OK;
Amit Blay8e2731c2015-04-28 21:54:55 +0300604 return;
Amit Blay6281ebc2015-01-11 14:44:08 +0200605}
606
607/* Verify the DIP and all protected partitions */
Amit Blay4aa292f2015-04-28 21:55:59 +0300608static void validate_DIP_and_firmware(mdtp_ext_partition_verification_t *ext_partition)
Amit Blay6281ebc2015-01-11 14:44:08 +0200609{
610 int ret;
Amit Blaydf42d2f2015-02-03 16:37:09 +0200611 DIP_t *enc_dip;
612 DIP_t *dec_dip;
Amit Blay6281ebc2015-01-11 14:44:08 +0200613 uint32_t verified = 0;
614 verify_result_t verify_result;
Amit Blaydf42d2f2015-02-03 16:37:09 +0200615 uint32_t block_size = mmc_get_device_blocksize();
Amit Blay4aa292f2015-04-28 21:55:59 +0300616 mdtp_cfg_t mdtp_cfg;
Amit Blay6281ebc2015-01-11 14:44:08 +0200617
618 enc_dip = malloc(ROUNDUP(sizeof(DIP_t), block_size));
619 if (enc_dip == NULL)
620 {
Reut Zysman18411272015-02-09 13:47:27 +0200621 dprintf(CRITICAL, "mdtp: validate_DIP_and_firmware: ERROR, cannot allocate DIP\n");
Amit Blay8e2731c2015-04-28 21:54:55 +0300622 display_error_msg(); /* This will never return */
Amit Blay6281ebc2015-01-11 14:44:08 +0200623 }
624
625 dec_dip = malloc(ROUNDUP(sizeof(DIP_t), block_size));
626 if (dec_dip == NULL)
627 {
Reut Zysman18411272015-02-09 13:47:27 +0200628 dprintf(CRITICAL, "mdtp: validate_DIP_and_firmware: ERROR, cannot allocate DIP\n");
Amit Blay6281ebc2015-01-11 14:44:08 +0200629 free(enc_dip);
Amit Blay8e2731c2015-04-28 21:54:55 +0300630 display_error_msg(); /* This will never return */
Amit Blay6281ebc2015-01-11 14:44:08 +0200631 }
632
633 /* Read the DIP holding the MDTP Firmware Lock state from the DIP partition */
634 ret = read_DIP(enc_dip);
635 if(ret < 0)
636 {
637 dprintf(CRITICAL, "mdtp: validate_DIP_and_firmware: ERROR, cannot read DIP\n");
Amit Blay8e2731c2015-04-28 21:54:55 +0300638 display_error_msg(); /* This will never return */
Amit Blay6281ebc2015-01-11 14:44:08 +0200639 }
640
641 /* Decrypt and verify the integrity of the DIP */
642 ret = mdtp_tzbsp_dec_verify_DIP(enc_dip, dec_dip, &verified);
643 if(ret < 0)
644 {
645 dprintf(CRITICAL, "mdtp: validate_DIP_and_firmware: ERROR, cannot verify DIP\n");
Amit Blay8e2731c2015-04-28 21:54:55 +0300646 display_error_msg(); /* This will never return */
Amit Blay6281ebc2015-01-11 14:44:08 +0200647 }
648
649 /* In case DIP integrity verification fails, notify the user and halt */
650 if(!verified)
651 {
652 dprintf(CRITICAL, "mdtp: validate_DIP_and_firmware: ERROR, corrupted DIP\n");
Amit Blay8e2731c2015-04-28 21:54:55 +0300653 display_error_msg(); /* This will never return */
Amit Blay6281ebc2015-01-11 14:44:08 +0200654 }
655
Amit Blay4aa292f2015-04-28 21:55:59 +0300656 /* Verify the integrity of the partitions which are protected, according to the content of the DIP */
657 verify_all_partitions(dec_dip, ext_partition, &verify_result);
658
659 mdtp_cfg = dec_dip->mdtp_cfg;
Amit Blay8e2731c2015-04-28 21:54:55 +0300660
661 /* Clear decrypted DIP since we don't need it anymore */
662 memset(dec_dip, 0, sizeof(DIP_t));
Amit Blay6281ebc2015-01-11 14:44:08 +0200663
Amit Blay4aa292f2015-04-28 21:55:59 +0300664
Amit Blay6281ebc2015-01-11 14:44:08 +0200665 if (verify_result == VERIFY_OK)
666 {
Reut Zysman18411272015-02-09 13:47:27 +0200667 dprintf(SPEW, "mdtp: validate_DIP_and_firmware: Verify OK\n");
Amit Blay6281ebc2015-01-11 14:44:08 +0200668 }
Amit Blay8e2731c2015-04-28 21:54:55 +0300669 else if (verify_result == VERIFY_SKIPPED)
670 {
671 dprintf(SPEW, "mdtp: validate_DIP_and_firmware: Verify skipped\n");
672 } else /* VERIFY_FAILED */
Amit Blay6281ebc2015-01-11 14:44:08 +0200673 {
674 dprintf(CRITICAL, "mdtp: validate_DIP_and_firmware: ERROR, corrupted firmware\n");
Amit Blay4aa292f2015-04-28 21:55:59 +0300675 display_recovery_ui(&mdtp_cfg);
Amit Blay6281ebc2015-01-11 14:44:08 +0200676 }
677
Amit Blay4aa292f2015-04-28 21:55:59 +0300678 memset(&mdtp_cfg, 0, sizeof(mdtp_cfg));
679
Amit Blay6281ebc2015-01-11 14:44:08 +0200680 free(enc_dip);
681 free(dec_dip);
682
683 return;
684}
685
686/********************************************************************************/
687
Amit Blay4aa292f2015-04-28 21:55:59 +0300688/** Entry point of the MDTP Firmware Lock.
689 * If needed, verify the DIP and all protected partitions.
690 * Allow passing information about partition verified using an external method
691 * (either boot or recovery). For boot and recovery, either use aboot's
692 * verification result, or use boot_verifier APIs to verify internally.
693 **/
694void mdtp_fwlock_verify_lock(mdtp_ext_partition_verification_t *ext_partition)
Amit Blay6281ebc2015-01-11 14:44:08 +0200695{
Amit Blaydf42d2f2015-02-03 16:37:09 +0200696 int ret;
697 bool enabled;
Amit Blay6281ebc2015-01-11 14:44:08 +0200698
Shay Nachmanibc10dfe2015-02-10 14:45:55 +0200699 /* sets the default value of this global to be MDTP not activated */
700 is_mdtp_activated = 0;
701
Amit Blay4aa292f2015-04-28 21:55:59 +0300702 do {
703 if (ext_partition == NULL)
704 {
705 dprintf(CRITICAL, "mdtp: mdtp_fwlock_verify_lock: ERROR, external partition is NULL\n");
706 display_error_msg(); /* This will never return */
707 break;
708 }
Amit Blay6281ebc2015-01-11 14:44:08 +0200709
Amit Blay4aa292f2015-04-28 21:55:59 +0300710 ret = mdtp_fuse_get_enabled(&enabled);
711 if(ret)
712 {
713 dprintf(CRITICAL, "mdtp: mdtp_fwlock_verify_lock: ERROR, cannot get enabled fuse\n");
714 display_error_msg(); /* This will never return */
715 }
716
717 /* Continue with Firmware Lock verification only if enabled by eFuse */
718 if (enabled)
719 {
720 /* This function will handle firmware verification failure via UI */
721 validate_DIP_and_firmware(ext_partition);
722 }
723 } while (0);
724
725 /* Disallow CIPHER_DIP SCM call from this point, unless we are in recovery */
726 /* The recovery image will disallow CIPHER_DIP SCM call by itself. */
727 if (ext_partition->partition != MDTP_PARTITION_RECOVERY)
Amit Blay6281ebc2015-01-11 14:44:08 +0200728 {
Amit Blay4aa292f2015-04-28 21:55:59 +0300729 mdtp_tzbsp_disallow_cipher_DIP();
Amit Blay6281ebc2015-01-11 14:44:08 +0200730 }
Amit Blay6281ebc2015-01-11 14:44:08 +0200731}
Shay Nachmanibc10dfe2015-02-10 14:45:55 +0200732/********************************************************************************/
733
734/** Indicates whether the MDTP is currently in ACTIVATED state **/
735int mdtp_activated(bool * activated){
736 if(is_mdtp_activated < 0){
737 /* mdtp_fwlock_verify_lock was not called before, the value is not valid */
738 return is_mdtp_activated;
739 }
740
741 *activated = is_mdtp_activated;
742 return 0;
743}
Amit Blay6281ebc2015-01-11 14:44:08 +0200744
745/********************************************************************************/
746
Amit Blay6281ebc2015-01-11 14:44:08 +0200747/* Decrypt a given DIP and verify its integrity */
Amit Blaydf42d2f2015-02-03 16:37:09 +0200748static int mdtp_tzbsp_dec_verify_DIP(DIP_t *enc_dip, DIP_t *dec_dip, uint32_t *verified)
Amit Blay6281ebc2015-01-11 14:44:08 +0200749{
Amit Blay6281ebc2015-01-11 14:44:08 +0200750 unsigned char hash[HASH_LEN];
751 SHA256_CTX sha256_ctx;
752 int ret;
753
754 ASSERT(enc_dip != NULL);
755 ASSERT(dec_dip != NULL);
756 ASSERT(verified != NULL);
757
Amit Blay4418fb42015-05-05 08:45:13 +0300758 arch_clean_invalidate_cache_range((addr_t)enc_dip, sizeof(DIP_t));
759 arch_invalidate_cache_range((addr_t)dec_dip, sizeof(DIP_t));
760
Amit Blay6281ebc2015-01-11 14:44:08 +0200761 ret = mdtp_cipher_dip_cmd((uint8_t*)enc_dip, sizeof(DIP_t),
762 (uint8_t*)dec_dip, sizeof(DIP_t),
763 DIP_DECRYPT);
764 if (ret)
765 {
766 dprintf(CRITICAL, "mdtp: mdtp_tzbsp_dec_verify_DIP: ERROR, cannot cipher DIP\n");
767 *verified = 0;
Amit Blay8e2731c2015-04-28 21:54:55 +0300768 memset(dec_dip, 0, sizeof(DIP_t));
Amit Blay6281ebc2015-01-11 14:44:08 +0200769 return -1;
770 }
771
Amit Blay4418fb42015-05-05 08:45:13 +0300772 arch_invalidate_cache_range((addr_t)dec_dip, sizeof(DIP_t));
773
Amit Blay6281ebc2015-01-11 14:44:08 +0200774 SHA256_Init(&sha256_ctx);
775 SHA256_Update(&sha256_ctx, dec_dip, sizeof(DIP_t) - HASH_LEN);
776 SHA256_Final(hash, &sha256_ctx);
777
Amit Blay8e2731c2015-04-28 21:54:55 +0300778 if (memcmp(hash, dec_dip->hash, HASH_LEN))
Amit Blay6281ebc2015-01-11 14:44:08 +0200779 {
780 *verified = 0;
Amit Blay8e2731c2015-04-28 21:54:55 +0300781 memset(dec_dip, 0, sizeof(DIP_t));
Amit Blay6281ebc2015-01-11 14:44:08 +0200782 }
783 else
784 {
785 *verified = 1;
786 }
787
788 return 0;
789}
790
Amit Blay4aa292f2015-04-28 21:55:59 +0300791/* Encrypt a given DIP and calculate its integrity information */
Amit Blaydf42d2f2015-02-03 16:37:09 +0200792static int mdtp_tzbsp_enc_hash_DIP(DIP_t *dec_dip, DIP_t *enc_dip)
Amit Blay6281ebc2015-01-11 14:44:08 +0200793{
Amit Blay6281ebc2015-01-11 14:44:08 +0200794 SHA256_CTX sha256_ctx;
795 int ret;
796
797 ASSERT(dec_dip != NULL);
798 ASSERT(enc_dip != NULL);
799
Amit Blay6281ebc2015-01-11 14:44:08 +0200800 SHA256_Init(&sha256_ctx);
801 SHA256_Update(&sha256_ctx, dec_dip, sizeof(DIP_t) - HASH_LEN);
Amit Blay8e2731c2015-04-28 21:54:55 +0300802 SHA256_Final(dec_dip->hash, &sha256_ctx);
Amit Blay6281ebc2015-01-11 14:44:08 +0200803
Amit Blay4418fb42015-05-05 08:45:13 +0300804 arch_clean_invalidate_cache_range((addr_t)dec_dip, sizeof(DIP_t));
805 arch_invalidate_cache_range((addr_t)enc_dip, sizeof(DIP_t));
806
Amit Blay6281ebc2015-01-11 14:44:08 +0200807 ret = mdtp_cipher_dip_cmd((uint8_t*)dec_dip, sizeof(DIP_t),
808 (uint8_t*)enc_dip, sizeof(DIP_t),
809 DIP_ENCRYPT);
810 if (ret)
811 {
812 dprintf(CRITICAL, "mdtp: mdtp_tzbsp_enc_hash_DIP: ERROR, cannot cipher DIP\n");
813 return -1;
814 }
815
Amit Blay4418fb42015-05-05 08:45:13 +0300816 arch_invalidate_cache_range((addr_t)enc_dip, sizeof(DIP_t));
817
Amit Blay6281ebc2015-01-11 14:44:08 +0200818 return 0;
819}
Amit Blay4aa292f2015-04-28 21:55:59 +0300820
821/* Disallow the CIPHER_DIP SCM call */
822static void mdtp_tzbsp_disallow_cipher_DIP(void)
823{
824 DIP_t *dip;
825 int i;
826
827 dip = malloc(sizeof(DIP_t));
828 if (dip == NULL)
829 {
830 dprintf(CRITICAL, "mdtp: mdtp_tzbsp_disallow_cipher_DIP: ERROR, cannot allocate DIP\n");
831 return;
832 }
833
834 /* Disallow the CIPHER_DIP SCM by calling it MAX_CIPHER_DIP_SCM_CALLS times */
835 for (i=0; i<MAX_CIPHER_DIP_SCM_CALLS; i++)
836 {
837 mdtp_tzbsp_enc_hash_DIP(dip, dip);
838 }
839
840 free(dip);
841}