blob: 01f907a278803819c29d11f0c2d358a8c2ae1a03 [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);
Rami Butsteinfaecf7f2015-06-04 16:39:30 +030065void free_mdtp_image(void);
Amit Blay8e2731c2015-04-28 21:54:55 +030066
Amit Blay6281ebc2015-01-11 14:44:08 +020067/********************************************************************************/
68
69/* Read the DIP from EMMC */
Amit Blaydf42d2f2015-02-03 16:37:09 +020070static int read_DIP(DIP_t *dip)
Amit Blay6281ebc2015-01-11 14:44:08 +020071{
72 unsigned long long ptn = 0;
73 uint32_t actual_partition_size;
Amit Blaydf42d2f2015-02-03 16:37:09 +020074 uint32_t block_size = mmc_get_device_blocksize();
Amit Blay6281ebc2015-01-11 14:44:08 +020075
76 int index = INVALID_PTN;
77
78 ASSERT(dip != NULL);
79
80 index = partition_get_index("dip");
81 ptn = partition_get_offset(index);
82
83 if(ptn == 0)
84 {
85 return -1;
86 }
87
88 actual_partition_size = ROUNDUP(sizeof(DIP_t), block_size);
89
90 if(mmc_read(ptn, (void *)dip, actual_partition_size))
91 {
92 dprintf(CRITICAL, "mdtp: read_DIP: ERROR, cannot read DIP info\n");
93 return -1;
94 }
95
Reut Zysman18411272015-02-09 13:47:27 +020096 dprintf(SPEW, "mdtp: read_DIP: SUCCESS, read %d bytes\n", actual_partition_size);
Amit Blay6281ebc2015-01-11 14:44:08 +020097
98 return 0;
99}
100
101/* Store the DIP into the EMMC */
Amit Blaydf42d2f2015-02-03 16:37:09 +0200102static int write_DIP(DIP_t *dip)
Amit Blay6281ebc2015-01-11 14:44:08 +0200103{
104 unsigned long long ptn = 0;
Amit Blaydf42d2f2015-02-03 16:37:09 +0200105 uint32_t block_size = mmc_get_device_blocksize();
Amit Blay6281ebc2015-01-11 14:44:08 +0200106
107 int index = INVALID_PTN;
108
109 ASSERT(dip != NULL);
110
111 index = partition_get_index("dip");
112 ptn = partition_get_offset(index);
Reut Zysman18411272015-02-09 13:47:27 +0200113
Amit Blay6281ebc2015-01-11 14:44:08 +0200114 if(ptn == 0)
115 {
116 return -1;
117 }
118
Reut Zysman18411272015-02-09 13:47:27 +0200119 if(mmc_write(ptn, ROUNDUP(sizeof(DIP_t), block_size), (void *)dip))
Amit Blay6281ebc2015-01-11 14:44:08 +0200120 {
Amit Blay8e2731c2015-04-28 21:54:55 +0300121 dprintf(CRITICAL, "mdtp: write_DIP: ERROR, cannot write DIP info\n");
Amit Blay6281ebc2015-01-11 14:44:08 +0200122 return -1;
123 }
124
Reut Zysman18411272015-02-09 13:47:27 +0200125 dprintf(SPEW, "mdtp: write_DIP: SUCCESS, write %d bytes\n", ROUNDUP(sizeof(DIP_t), block_size));
126
Amit Blay6281ebc2015-01-11 14:44:08 +0200127 return 0;
128}
129
Reut Zysman18411272015-02-09 13:47:27 +0200130/* Deactivate MDTP by storing the default DIP into the EMMC */
131static void write_deactivated_DIP()
Amit Blay6281ebc2015-01-11 14:44:08 +0200132{
Amit Blaydf42d2f2015-02-03 16:37:09 +0200133 DIP_t *enc_dip;
134 DIP_t *dec_dip;
Amit Blay6281ebc2015-01-11 14:44:08 +0200135 int ret;
136
137 enc_dip = malloc(sizeof(DIP_t));
138 if (enc_dip == NULL)
139 {
Reut Zysman18411272015-02-09 13:47:27 +0200140 dprintf(CRITICAL, "mdtp: write_deactivated_DIP: ERROR, cannot allocate DIP\n");
Amit Blay6281ebc2015-01-11 14:44:08 +0200141 return;
142 }
143
144 dec_dip = malloc(sizeof(DIP_t));
145 if (dec_dip == NULL)
146 {
Reut Zysman18411272015-02-09 13:47:27 +0200147 dprintf(CRITICAL, "mdtp: write_deactivated_DIP: ERROR, cannot allocate DIP\n");
Amit Blay6281ebc2015-01-11 14:44:08 +0200148 free(enc_dip);
149 return;
150 }
151
152 memset(dec_dip, 0, sizeof(DIP_t));
153
154 dec_dip->status = DIP_STATUS_DEACTIVATED;
Amit Blay8e2731c2015-04-28 21:54:55 +0300155 dec_dip->version = g_mdtp_version;
Amit Blay6281ebc2015-01-11 14:44:08 +0200156
157 ret = mdtp_tzbsp_enc_hash_DIP(dec_dip, enc_dip);
158 if(ret < 0)
159 {
Reut Zysman18411272015-02-09 13:47:27 +0200160 dprintf(CRITICAL, "mdtp: write_deactivated_DIP: ERROR, cannot cipher DIP\n");
Amit Blay6281ebc2015-01-11 14:44:08 +0200161 goto out;
162 }
163
164 ret = write_DIP(enc_dip);
165 if(ret < 0)
166 {
Reut Zysman18411272015-02-09 13:47:27 +0200167 dprintf(CRITICAL, "mdtp: write_deactivated_DIP: ERROR, cannot write DIP\n");
Amit Blay6281ebc2015-01-11 14:44:08 +0200168 goto out;
169 }
170
171out:
172 free(enc_dip);
173 free(dec_dip);
174}
175
176/* Validate a hash calculated on entire given partition */
Amit Blay8e2731c2015-04-28 21:54:55 +0300177static int verify_partition_single_hash(char *name, uint64_t size, DIP_hash_table_entry_t *hash_table)
Amit Blay6281ebc2015-01-11 14:44:08 +0200178{
Amit Blay8e2731c2015-04-28 21:54:55 +0300179 unsigned char digest[HASH_LEN]={0};
Amit Blay6281ebc2015-01-11 14:44:08 +0200180 unsigned long long ptn = 0;
181 int index = INVALID_PTN;
Amit Blay4aa292f2015-04-28 21:55:59 +0300182 unsigned char *buf = (unsigned char *)target_get_scratch_address() + MDTP_SCRATCH_OFFSET;
Amit Blaydf42d2f2015-02-03 16:37:09 +0200183 uint32_t block_size = mmc_get_device_blocksize();
Amit Blay8e2731c2015-04-28 21:54:55 +0300184 uint64_t actual_partition_size = ROUNDUP(size, block_size);
Amit Blay6281ebc2015-01-11 14:44:08 +0200185
Amit Blay8e2731c2015-04-28 21:54:55 +0300186 dprintf(SPEW, "mdtp: verify_partition_single_hash: %s, %llu\n", name, size);
Amit Blay6281ebc2015-01-11 14:44:08 +0200187
188 ASSERT(name != NULL);
189 ASSERT(hash_table != NULL);
Amit Blay8e2731c2015-04-28 21:54:55 +0300190 ASSERT(size > 0);
Amit Blay6281ebc2015-01-11 14:44:08 +0200191
192 index = partition_get_index(name);
193 ptn = partition_get_offset(index);
194
195 if(ptn == 0) {
196 dprintf(CRITICAL, "mdtp: verify_partition_single_hash: %s: partition was not found\n", name);
197 return -1;
198 }
199
Amit Blay6281ebc2015-01-11 14:44:08 +0200200 if (mmc_read(ptn, (void *)buf, actual_partition_size))
201 {
Amit Blay8e2731c2015-04-28 21:54:55 +0300202 dprintf(CRITICAL, "mdtp: verify_partition_single_hash: %s: mmc_read() fail.\n", name);
Amit Blay6281ebc2015-01-11 14:44:08 +0200203 return -1;
204 }
205
Amit Blayfe649212015-01-25 11:21:10 +0200206 /* calculating the hash value using HW crypto */
207 target_crypto_init_params();
Amit Blay8e2731c2015-04-28 21:54:55 +0300208 hash_find(buf, size, digest, CRYPTO_AUTH_ALG_SHA256);
Amit Blay6281ebc2015-01-11 14:44:08 +0200209
Amit Blay8e2731c2015-04-28 21:54:55 +0300210 if (memcmp(digest, hash_table->hash, HASH_LEN))
Amit Blay6281ebc2015-01-11 14:44:08 +0200211 {
212 dprintf(CRITICAL, "mdtp: verify_partition_single_hash: %s: Failed partition hash verification\n", name);
213
214 return -1;
215 }
216
Reut Zysman18411272015-02-09 13:47:27 +0200217 dprintf(SPEW, "verify_partition_single_hash: %s: VERIFIED!\n", name);
Amit Blay6281ebc2015-01-11 14:44:08 +0200218
219 return 0;
220}
221
222/* Validate a hash table calculated per block of a given partition */
Amit Blaydf42d2f2015-02-03 16:37:09 +0200223static int verify_partition_block_hash(char *name,
Amit Blay8e2731c2015-04-28 21:54:55 +0300224 uint64_t size,
Amit Blay6281ebc2015-01-11 14:44:08 +0200225 uint32_t verify_num_blocks,
Amit Blaydf42d2f2015-02-03 16:37:09 +0200226 DIP_hash_table_entry_t *hash_table,
Amit Blay8e2731c2015-04-28 21:54:55 +0300227 uint8_t *force_verify_block)
Amit Blay6281ebc2015-01-11 14:44:08 +0200228{
Amit Blay8e2731c2015-04-28 21:54:55 +0300229 unsigned char digest[HASH_LEN]={0};
Amit Blay6281ebc2015-01-11 14:44:08 +0200230 unsigned long long ptn = 0;
231 int index = INVALID_PTN;
Amit Blay4aa292f2015-04-28 21:55:59 +0300232 unsigned char *buf = (unsigned char *)target_get_scratch_address() + MDTP_SCRATCH_OFFSET;
Amit Blay6281ebc2015-01-11 14:44:08 +0200233 uint32_t bytes_to_read;
234 uint32_t block_num = 0;
Amit Blay8e2731c2015-04-28 21:54:55 +0300235 uint32_t total_num_blocks = ((size - 1) / MDTP_FWLOCK_BLOCK_SIZE) + 1;
236 uint32_t rand_int;
237 uint32_t block_size = mmc_get_device_blocksize();
Amit Blay6281ebc2015-01-11 14:44:08 +0200238
Amit Blay8e2731c2015-04-28 21:54:55 +0300239 dprintf(SPEW, "mdtp: verify_partition_block_hash: %s, %llu\n", name, size);
Amit Blay6281ebc2015-01-11 14:44:08 +0200240
241 ASSERT(name != NULL);
242 ASSERT(hash_table != NULL);
Amit Blay8e2731c2015-04-28 21:54:55 +0300243 ASSERT(size > 0);
244 ASSERT(force_verify_block != NULL);
Amit Blay6281ebc2015-01-11 14:44:08 +0200245
246 index = partition_get_index(name);
247 ptn = partition_get_offset(index);
248
249 if(ptn == 0) {
250 dprintf(CRITICAL, "mdtp: verify_partition_block_hash: %s: partition was not found\n", name);
251 return -1;
252 }
253
Amit Blayfe649212015-01-25 11:21:10 +0200254 /* initiating parameters for hash calculation using HW crypto */
255 target_crypto_init_params();
Amit Blay8e2731c2015-04-28 21:54:55 +0300256 if (check_aboot_addr_range_overlap((uint32_t)buf, ROUNDUP(MDTP_FWLOCK_BLOCK_SIZE, block_size)))
257 {
258 dprintf(CRITICAL, "mdtp: verify_partition_block_hash: %s: image buffer address overlaps with aboot addresses.\n", name);
259 return -1;
260 }
Amit Blayfe649212015-01-25 11:21:10 +0200261
Amit Blay6281ebc2015-01-11 14:44:08 +0200262 while (MDTP_FWLOCK_BLOCK_SIZE * block_num < size)
263 {
264 if (*force_verify_block == 0)
265 {
Amit Blay8e2731c2015-04-28 21:54:55 +0300266 if(scm_random((uint32_t *)&rand_int, sizeof(rand_int)))
267 {
268 dprintf(CRITICAL,"mdtp: scm_call for random failed\n");
269 return -1;
270 }
271
Amit Blay6281ebc2015-01-11 14:44:08 +0200272 /* Skip validation of this block with probability of verify_num_blocks / total_num_blocks */
Amit Blay8e2731c2015-04-28 21:54:55 +0300273 if ((rand_int % total_num_blocks) >= verify_num_blocks)
Amit Blay6281ebc2015-01-11 14:44:08 +0200274 {
275 block_num++;
276 hash_table += 1;
277 force_verify_block += 1;
278 dprintf(CRITICAL, "mdtp: verify_partition_block_hash: %s: skipped verification of block %d\n", name, block_num);
279 continue;
280 }
281 }
282
Amit Blay6281ebc2015-01-11 14:44:08 +0200283 if ((size - (MDTP_FWLOCK_BLOCK_SIZE * block_num) < MDTP_FWLOCK_BLOCK_SIZE))
284 {
285 bytes_to_read = size - (MDTP_FWLOCK_BLOCK_SIZE * block_num);
286 } else
287 {
288 bytes_to_read = MDTP_FWLOCK_BLOCK_SIZE;
289 }
290
Amit Blay8e2731c2015-04-28 21:54:55 +0300291 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 +0200292 {
293 dprintf(CRITICAL, "mdtp: verify_partition_block_hash: %s: mmc_read() fail.\n", name);
294 return -1;
295 }
296
Amit Blayfe649212015-01-25 11:21:10 +0200297 /* calculating the hash value using HW */
Amit Blay8e2731c2015-04-28 21:54:55 +0300298 hash_find(buf, bytes_to_read, digest, CRYPTO_AUTH_ALG_SHA256);
Amit Blay6281ebc2015-01-11 14:44:08 +0200299
Amit Blay8e2731c2015-04-28 21:54:55 +0300300 if (memcmp(digest, hash_table->hash, HASH_LEN))
Amit Blay6281ebc2015-01-11 14:44:08 +0200301 {
302 dprintf(CRITICAL, "mdtp: verify_partition_block_hash: %s: Failed partition hash[%d] verification\n", name, block_num);
303 return -1;
304 }
305
306 block_num++;
307 hash_table += 1;
308 force_verify_block += 1;
309 }
310
Reut Zysman18411272015-02-09 13:47:27 +0200311 dprintf(SPEW, "verify_partition_block_hash: %s: VERIFIED!\n", name);
Amit Blay6281ebc2015-01-11 14:44:08 +0200312
313 return 0;
314}
315
Amit Blay8e2731c2015-04-28 21:54:55 +0300316/* Validate the partition parameters read from DIP */
317static int validate_partition_params(uint64_t size,
Amit Blay6281ebc2015-01-11 14:44:08 +0200318 mdtp_fwlock_mode_t hash_mode,
Amit Blay8e2731c2015-04-28 21:54:55 +0300319 uint32_t verify_ratio)
Amit Blay6281ebc2015-01-11 14:44:08 +0200320{
Amit Blay8e2731c2015-04-28 21:54:55 +0300321 if (size == 0 || size > (uint64_t)MDTP_FWLOCK_BLOCK_SIZE * (uint64_t)MAX_BLOCKS ||
322 hash_mode >= MDTP_FWLOCK_MODE_SIZE || verify_ratio > 100)
Amit Blay6281ebc2015-01-11 14:44:08 +0200323 {
Amit Blay8e2731c2015-04-28 21:54:55 +0300324 dprintf(CRITICAL, "mdtp: validate_partition_params: error, size=%llu, hash_mode=%d, verify_ratio=%d\n",
325 size, hash_mode, verify_ratio);
Amit Blay6281ebc2015-01-11 14:44:08 +0200326 return -1;
327 }
328
329 return 0;
330}
331
Amit Blay8e2731c2015-04-28 21:54:55 +0300332/* Verify a given partitinon */
333static int verify_partition(char *name,
334 uint64_t size,
335 mdtp_fwlock_mode_t hash_mode,
336 uint32_t verify_num_blocks,
337 DIP_hash_table_entry_t *hash_table,
338 uint8_t *force_verify_block)
339{
340 if (hash_mode == MDTP_FWLOCK_MODE_SINGLE)
341 {
342 return verify_partition_single_hash(name, size, hash_table);
343 } else if (hash_mode == MDTP_FWLOCK_MODE_BLOCK || hash_mode == MDTP_FWLOCK_MODE_FILES)
344 {
345 return verify_partition_block_hash(name, size, verify_num_blocks, hash_table, force_verify_block);
346 }
347
348 /* Illegal value of hash_mode */
349 return -1;
350}
351
352static int validate_dip(DIP_t *dip)
353{
354 uint8_t *dip_p;
355
356 ASSERT(dip != NULL);
357
358 /* Make sure DIP version is supported by current SW */
359 if (MDTP_GET_MAJOR_VERSION(dip->version) != MDTP_MAJOR_VERSION)
360 {
361 dprintf(CRITICAL, "mdtp: validate_dip: Wrong DIP version 0x%x\n", dip->version);
362 return -1;
363 }
364
365 /* Make sure that deactivated DIP content is as expected */
366 if (dip->status == DIP_STATUS_DEACTIVATED)
367 {
368 dip_p = (uint8_t*)&dip->mdtp_cfg;
369 while (dip_p < dip->hash)
370 {
371 if (*dip_p != 0)
372 {
373 dprintf(CRITICAL, "mdtp: validate_dip: error in deactivated DIP\n");
374 return -1;
375 }
376 dip_p++;
377 }
378 }
379
380 return 0;
381}
382
Reut Zysman18411272015-02-09 13:47:27 +0200383/* Display the recovery UI to allow the user to enter the PIN and continue boot */
Amit Blay4aa292f2015-04-28 21:55:59 +0300384static void display_recovery_ui(mdtp_cfg_t *mdtp_cfg)
Reut Zysman18411272015-02-09 13:47:27 +0200385{
386 uint32_t pin_length = 0;
387 char entered_pin[MDTP_MAX_PIN_LEN+1] = {0};
388 uint32_t i;
Amit Blay8e2731c2015-04-28 21:54:55 +0300389 char pin_mismatch = 0;
Reut Zysman18411272015-02-09 13:47:27 +0200390
Amit Blay4aa292f2015-04-28 21:55:59 +0300391 if (mdtp_cfg->enable_local_pin_authentication)
Reut Zysman18411272015-02-09 13:47:27 +0200392 {
393 dprintf(SPEW, "mdtp: display_recovery_ui: Local deactivation enabled\n");
394
Amit Blay4aa292f2015-04-28 21:55:59 +0300395 pin_length = strlen(mdtp_cfg->mdtp_pin.mdtp_pin);
Reut Zysman18411272015-02-09 13:47:27 +0200396
397 if (pin_length > MDTP_MAX_PIN_LEN || pin_length < MDTP_MIN_PIN_LEN)
398 {
399 dprintf(CRITICAL, "mdtp: display_recovery_ui: Error, invalid PIN length\n");
Amit Blay8e2731c2015-04-28 21:54:55 +0300400 display_error_msg(); /* This will never return */
Reut Zysman18411272015-02-09 13:47:27 +0200401 }
402
403 // Set entered_pin to initial '0' string + null terminator
404 for (i=0; i<pin_length; i++)
405 {
406 entered_pin[i] = '0';
407 }
408
409 // Allow the user to enter the PIN as many times as he wishes
410 // (with INVALID_PIN_DELAY_MSECONDS after each failed attempt)
411 while (1)
412 {
Amit Blay8e2731c2015-04-28 21:54:55 +0300413 get_pin_from_user(entered_pin, pin_length);
Reut Zysman18411272015-02-09 13:47:27 +0200414
Amit Blay8e2731c2015-04-28 21:54:55 +0300415 // Go over the entire PIN in any case, to prevent side-channel attacks
416 for (i=0; i<pin_length; i++)
417 {
Amit Blay4aa292f2015-04-28 21:55:59 +0300418 pin_mismatch |= mdtp_cfg->mdtp_pin.mdtp_pin[i] ^ entered_pin[i];
Amit Blay8e2731c2015-04-28 21:54:55 +0300419 }
Reut Zysman18411272015-02-09 13:47:27 +0200420
Amit Blay8e2731c2015-04-28 21:54:55 +0300421 if (0 == pin_mismatch)
422 {
423 // Valid PIN - deactivate and continue boot
424 dprintf(SPEW, "mdtp: display_recovery_ui: valid PIN, continue boot\n");
425 write_deactivated_DIP();
Rami Butsteinfaecf7f2015-06-04 16:39:30 +0300426 goto out;
Amit Blay8e2731c2015-04-28 21:54:55 +0300427 }
428 else
429 {
430 // Invalid PIN - display an appropriate message (which also includes a wait
431 // for INVALID_PIN_DELAY_MSECONDS), and allow the user to try again
432 dprintf(CRITICAL, "mdtp: display_recovery_ui: ERROR, invalid PIN\n");
433 display_invalid_pin_msg();
Reut Zysman18411272015-02-09 13:47:27 +0200434
Amit Blay8e2731c2015-04-28 21:54:55 +0300435 pin_mismatch = 0;
436 }
Reut Zysman18411272015-02-09 13:47:27 +0200437 }
438 }
439 else
440 {
441 dprintf(CRITICAL, "mdtp: display_recovery_ui: Local deactivation disabled, unable to display recovery UI\n");
Amit Blay8e2731c2015-04-28 21:54:55 +0300442 display_error_msg(); /* This will never return */
Reut Zysman18411272015-02-09 13:47:27 +0200443 }
Rami Butsteinfaecf7f2015-06-04 16:39:30 +0300444
445 out:
446 free_mdtp_image();
Reut Zysman18411272015-02-09 13:47:27 +0200447}
448
Amit Blay4aa292f2015-04-28 21:55:59 +0300449/* Verify the boot or recovery partitions using boot_verifier. */
450static int verify_ext_partition(mdtp_ext_partition_verification_t *ext_partition)
451{
452 int ret = 0;
453 bool restore_to_orange = false;
454 unsigned long long ptn = 0;
455 int index = INVALID_PTN;
456
457 /* If image was already verified in aboot, return its status */
458 if (ext_partition->integrity_state == MDTP_PARTITION_STATE_INVALID)
459 {
460 dprintf(CRITICAL, "mdtp: verify_ext_partition: image %s verified externally and failed.\n",
461 ext_partition->partition == MDTP_PARTITION_BOOT ? "boot" : "recovery");
462 return -1;
463 }
464 else if (ext_partition->integrity_state == MDTP_PARTITION_STATE_VALID)
465 {
466 dprintf(CRITICAL, "mdtp: verify_ext_partition: image %s verified externally succesfully.\n",
467 ext_partition->partition == MDTP_PARTITION_BOOT ? "boot" : "recovery");
468 return 0;
469 }
470
471 /* If image was not verified in aboot, verify it ourselves using boot_verifier. */
472
473 /* 1) Initialize keystore. We don't care about return value which is Verified Boot's state machine state. */
474 boot_verify_keystore_init();
475
476 /* 2) If boot_verifier is ORANGE, it will prevent verifying an image. So
477 * temporarly change boot_verifier state to BOOT_INIT.
478 */
479 if (boot_verify_get_state() == ORANGE)
480 restore_to_orange = true;
481 boot_verify_send_event(BOOT_INIT);
482
483 switch (ext_partition->partition)
484 {
485 case MDTP_PARTITION_BOOT:
486 case MDTP_PARTITION_RECOVERY:
487
488 /* 3) Signature may or may not be at the end of the image. Read the signature if needed. */
489 if (!ext_partition->sig_avail)
490 {
491 if (check_aboot_addr_range_overlap((uint32_t)(ext_partition->image_addr + ext_partition->image_size), ext_partition->page_size))
492 {
493 dprintf(CRITICAL, "ERROR: Signature read buffer address overlaps with aboot addresses.\n");
494 return -1;
495 }
496
497 index = partition_get_index(ext_partition->partition == MDTP_PARTITION_BOOT ? "boot" : "recovery");
498 ptn = partition_get_offset(index);
499 if(ptn == 0) {
500 dprintf(CRITICAL, "ERROR: partition %s not found\n",
501 ext_partition->partition == MDTP_PARTITION_BOOT ? "boot" : "recovery");
502 return -1;
503 }
504
505 if(mmc_read(ptn + ext_partition->image_size, (void *)(ext_partition->image_addr + ext_partition->image_size), ext_partition->page_size))
506 {
507 dprintf(CRITICAL, "ERROR: Cannot read %s image signature\n",
508 ext_partition->partition == MDTP_PARTITION_BOOT ? "boot" : "recovery");
509 return -1;
510 }
511 }
512
513 /* 4) Verify the image using its signature. */
514 ret = boot_verify_image((unsigned char *)ext_partition->image_addr,
515 ext_partition->image_size,
Amit Blay59fad252015-05-17 17:27:17 +0300516 ext_partition->partition == MDTP_PARTITION_BOOT ? "/boot" : "/recovery");
Amit Blay4aa292f2015-04-28 21:55:59 +0300517 break;
518
519 default:
520 /* Only boot and recovery are legal here */
521 dprintf(CRITICAL, "ERROR: wrong partition %d\n", ext_partition->partition);
522 return -1;
523 }
524
525 if (ret)
526 {
527 dprintf(INFO, "mdtp: verify_ext_partition: image %s verified succesfully in MDTP.\n",
528 ext_partition->partition == MDTP_PARTITION_BOOT ? "boot" : "recovery");
529 }
530 else
531 {
532 dprintf(CRITICAL, "mdtp: verify_ext_partition: image %s verification failed in MDTP.\n",
533 ext_partition->partition == MDTP_PARTITION_BOOT ? "boot" : "recovery");
534 }
535
536 /* 5) Restore the right boot_verifier state upon exit. */
537 if (restore_to_orange)
538 {
539 boot_verify_send_event(DEV_UNLOCK);
540 }
541
542 return ret ? 0 : -1;
543}
544
Amit Blay6281ebc2015-01-11 14:44:08 +0200545/* Verify all protected partitinons according to the DIP */
Amit Blay4aa292f2015-04-28 21:55:59 +0300546static void verify_all_partitions(DIP_t *dip,
547 mdtp_ext_partition_verification_t *ext_partition,
548 verify_result_t *verify_result)
Amit Blay6281ebc2015-01-11 14:44:08 +0200549{
550 int i;
Amit Blay4aa292f2015-04-28 21:55:59 +0300551 int verify_failure = 0;
552 int ext_partition_verify_failure = 0;
Amit Blay6281ebc2015-01-11 14:44:08 +0200553 uint32_t total_num_blocks;
554
555 ASSERT(dip != NULL);
556 ASSERT(verify_result != NULL);
557
558 *verify_result = VERIFY_FAILED;
559
Amit Blay8e2731c2015-04-28 21:54:55 +0300560 if (validate_dip(dip))
561 {
562 dprintf(CRITICAL, "mdtp: verify_all_partitions: failed DIP validation\n");
563 return;
564 }
565
Amit Blay6281ebc2015-01-11 14:44:08 +0200566 if (dip->status == DIP_STATUS_DEACTIVATED)
567 {
568 *verify_result = VERIFY_SKIPPED;
Amit Blay8e2731c2015-04-28 21:54:55 +0300569 return;
Amit Blay6281ebc2015-01-11 14:44:08 +0200570 }
Amit Blay8e2731c2015-04-28 21:54:55 +0300571 else
Amit Blay6281ebc2015-01-11 14:44:08 +0200572 {
Amit Blay8a510302015-08-17 09:20:01 +0300573 if (ext_partition->partition != MDTP_PARTITION_NONE)
Amit Blay6281ebc2015-01-11 14:44:08 +0200574 {
Amit Blay8a510302015-08-17 09:20:01 +0300575 for(i=0; i<MAX_PARTITIONS; i++)
Amit Blay6281ebc2015-01-11 14:44:08 +0200576 {
Amit Blay8a510302015-08-17 09:20:01 +0300577 if(dip->partition_cfg[i].lock_enabled && dip->partition_cfg[i].size)
Amit Blay8e2731c2015-04-28 21:54:55 +0300578 {
Amit Blay8a510302015-08-17 09:20:01 +0300579 total_num_blocks = ((dip->partition_cfg[i].size - 1) / MDTP_FWLOCK_BLOCK_SIZE);
580 if (validate_partition_params(dip->partition_cfg[i].size,
581 dip->partition_cfg[i].hash_mode,
582 dip->partition_cfg[i].verify_ratio))
583 {
584 dprintf(CRITICAL, "mdtp: verify_all_partitions: Wrong partition parameters\n");
585 verify_failure = TRUE;
586 break;
587 }
Amit Blay6281ebc2015-01-11 14:44:08 +0200588
Amit Blay8a510302015-08-17 09:20:01 +0300589 verify_failure |= (verify_partition(dip->partition_cfg[i].name,
590 dip->partition_cfg[i].size,
591 dip->partition_cfg[i].hash_mode,
592 (dip->partition_cfg[i].verify_ratio * total_num_blocks) / 100,
593 dip->partition_cfg[i].hash_table,
594 dip->partition_cfg[i].force_verify_block) != 0);
595 }
596 }
597
598 ext_partition_verify_failure = verify_ext_partition(ext_partition);
599
600 if (verify_failure || ext_partition_verify_failure)
601 {
602 dprintf(CRITICAL, "mdtp: verify_all_partitions: Failed partition verification\n");
603 return;
Amit Blay6281ebc2015-01-11 14:44:08 +0200604 }
605 }
Shay Nachmanibc10dfe2015-02-10 14:45:55 +0200606 is_mdtp_activated = 1;
Amit Blay6281ebc2015-01-11 14:44:08 +0200607 }
608
609 *verify_result = VERIFY_OK;
Amit Blay8e2731c2015-04-28 21:54:55 +0300610 return;
Amit Blay6281ebc2015-01-11 14:44:08 +0200611}
612
613/* Verify the DIP and all protected partitions */
Amit Blay4aa292f2015-04-28 21:55:59 +0300614static void validate_DIP_and_firmware(mdtp_ext_partition_verification_t *ext_partition)
Amit Blay6281ebc2015-01-11 14:44:08 +0200615{
616 int ret;
Amit Blaydf42d2f2015-02-03 16:37:09 +0200617 DIP_t *enc_dip;
618 DIP_t *dec_dip;
Amit Blay6281ebc2015-01-11 14:44:08 +0200619 uint32_t verified = 0;
620 verify_result_t verify_result;
Amit Blaydf42d2f2015-02-03 16:37:09 +0200621 uint32_t block_size = mmc_get_device_blocksize();
Amit Blay4aa292f2015-04-28 21:55:59 +0300622 mdtp_cfg_t mdtp_cfg;
Amit Blay6281ebc2015-01-11 14:44:08 +0200623
624 enc_dip = malloc(ROUNDUP(sizeof(DIP_t), block_size));
625 if (enc_dip == NULL)
626 {
Reut Zysman18411272015-02-09 13:47:27 +0200627 dprintf(CRITICAL, "mdtp: validate_DIP_and_firmware: ERROR, cannot allocate DIP\n");
Amit Blay8e2731c2015-04-28 21:54:55 +0300628 display_error_msg(); /* This will never return */
Amit Blay6281ebc2015-01-11 14:44:08 +0200629 }
630
631 dec_dip = malloc(ROUNDUP(sizeof(DIP_t), block_size));
632 if (dec_dip == NULL)
633 {
Reut Zysman18411272015-02-09 13:47:27 +0200634 dprintf(CRITICAL, "mdtp: validate_DIP_and_firmware: ERROR, cannot allocate DIP\n");
Amit Blay6281ebc2015-01-11 14:44:08 +0200635 free(enc_dip);
Amit Blay8e2731c2015-04-28 21:54:55 +0300636 display_error_msg(); /* This will never return */
Amit Blay6281ebc2015-01-11 14:44:08 +0200637 }
638
639 /* Read the DIP holding the MDTP Firmware Lock state from the DIP partition */
640 ret = read_DIP(enc_dip);
641 if(ret < 0)
642 {
643 dprintf(CRITICAL, "mdtp: validate_DIP_and_firmware: ERROR, cannot read DIP\n");
Amit Blay8e2731c2015-04-28 21:54:55 +0300644 display_error_msg(); /* This will never return */
Amit Blay6281ebc2015-01-11 14:44:08 +0200645 }
646
647 /* Decrypt and verify the integrity of the DIP */
648 ret = mdtp_tzbsp_dec_verify_DIP(enc_dip, dec_dip, &verified);
649 if(ret < 0)
650 {
651 dprintf(CRITICAL, "mdtp: validate_DIP_and_firmware: ERROR, cannot verify DIP\n");
Amit Blay8e2731c2015-04-28 21:54:55 +0300652 display_error_msg(); /* This will never return */
Amit Blay6281ebc2015-01-11 14:44:08 +0200653 }
654
655 /* In case DIP integrity verification fails, notify the user and halt */
656 if(!verified)
657 {
658 dprintf(CRITICAL, "mdtp: validate_DIP_and_firmware: ERROR, corrupted DIP\n");
Amit Blay8e2731c2015-04-28 21:54:55 +0300659 display_error_msg(); /* This will never return */
Amit Blay6281ebc2015-01-11 14:44:08 +0200660 }
661
Amit Blay4aa292f2015-04-28 21:55:59 +0300662 /* Verify the integrity of the partitions which are protected, according to the content of the DIP */
663 verify_all_partitions(dec_dip, ext_partition, &verify_result);
664
665 mdtp_cfg = dec_dip->mdtp_cfg;
Amit Blay8e2731c2015-04-28 21:54:55 +0300666
667 /* Clear decrypted DIP since we don't need it anymore */
668 memset(dec_dip, 0, sizeof(DIP_t));
Amit Blay6281ebc2015-01-11 14:44:08 +0200669
Amit Blay4aa292f2015-04-28 21:55:59 +0300670
Amit Blay6281ebc2015-01-11 14:44:08 +0200671 if (verify_result == VERIFY_OK)
672 {
Reut Zysman18411272015-02-09 13:47:27 +0200673 dprintf(SPEW, "mdtp: validate_DIP_and_firmware: Verify OK\n");
Amit Blay6281ebc2015-01-11 14:44:08 +0200674 }
Amit Blay8e2731c2015-04-28 21:54:55 +0300675 else if (verify_result == VERIFY_SKIPPED)
676 {
677 dprintf(SPEW, "mdtp: validate_DIP_and_firmware: Verify skipped\n");
678 } else /* VERIFY_FAILED */
Amit Blay6281ebc2015-01-11 14:44:08 +0200679 {
680 dprintf(CRITICAL, "mdtp: validate_DIP_and_firmware: ERROR, corrupted firmware\n");
Amit Blay4aa292f2015-04-28 21:55:59 +0300681 display_recovery_ui(&mdtp_cfg);
Amit Blay6281ebc2015-01-11 14:44:08 +0200682 }
683
Amit Blay4aa292f2015-04-28 21:55:59 +0300684 memset(&mdtp_cfg, 0, sizeof(mdtp_cfg));
685
Amit Blay6281ebc2015-01-11 14:44:08 +0200686 free(enc_dip);
687 free(dec_dip);
688
689 return;
690}
691
692/********************************************************************************/
693
Amit Blay4aa292f2015-04-28 21:55:59 +0300694/** Entry point of the MDTP Firmware Lock.
695 * If needed, verify the DIP and all protected partitions.
696 * Allow passing information about partition verified using an external method
697 * (either boot or recovery). For boot and recovery, either use aboot's
698 * verification result, or use boot_verifier APIs to verify internally.
699 **/
700void mdtp_fwlock_verify_lock(mdtp_ext_partition_verification_t *ext_partition)
Amit Blay6281ebc2015-01-11 14:44:08 +0200701{
Amit Blaydf42d2f2015-02-03 16:37:09 +0200702 int ret;
703 bool enabled;
Amit Blay6281ebc2015-01-11 14:44:08 +0200704
Shay Nachmanibc10dfe2015-02-10 14:45:55 +0200705 /* sets the default value of this global to be MDTP not activated */
706 is_mdtp_activated = 0;
707
Amit Blay4aa292f2015-04-28 21:55:59 +0300708 do {
709 if (ext_partition == NULL)
710 {
711 dprintf(CRITICAL, "mdtp: mdtp_fwlock_verify_lock: ERROR, external partition is NULL\n");
712 display_error_msg(); /* This will never return */
713 break;
714 }
Amit Blay6281ebc2015-01-11 14:44:08 +0200715
Amit Blay4aa292f2015-04-28 21:55:59 +0300716 ret = mdtp_fuse_get_enabled(&enabled);
717 if(ret)
718 {
719 dprintf(CRITICAL, "mdtp: mdtp_fwlock_verify_lock: ERROR, cannot get enabled fuse\n");
720 display_error_msg(); /* This will never return */
721 }
722
723 /* Continue with Firmware Lock verification only if enabled by eFuse */
724 if (enabled)
725 {
726 /* This function will handle firmware verification failure via UI */
727 validate_DIP_and_firmware(ext_partition);
728 }
729 } while (0);
730
731 /* Disallow CIPHER_DIP SCM call from this point, unless we are in recovery */
732 /* The recovery image will disallow CIPHER_DIP SCM call by itself. */
Amit Blay8a510302015-08-17 09:20:01 +0300733 if (ext_partition->partition == MDTP_PARTITION_BOOT)
Amit Blay6281ebc2015-01-11 14:44:08 +0200734 {
Amit Blay4aa292f2015-04-28 21:55:59 +0300735 mdtp_tzbsp_disallow_cipher_DIP();
Amit Blay6281ebc2015-01-11 14:44:08 +0200736 }
Amit Blay6281ebc2015-01-11 14:44:08 +0200737}
Shay Nachmanibc10dfe2015-02-10 14:45:55 +0200738/********************************************************************************/
739
740/** Indicates whether the MDTP is currently in ACTIVATED state **/
741int mdtp_activated(bool * activated){
742 if(is_mdtp_activated < 0){
743 /* mdtp_fwlock_verify_lock was not called before, the value is not valid */
744 return is_mdtp_activated;
745 }
746
747 *activated = is_mdtp_activated;
748 return 0;
749}
Amit Blay6281ebc2015-01-11 14:44:08 +0200750
751/********************************************************************************/
752
Amit Blay6281ebc2015-01-11 14:44:08 +0200753/* Decrypt a given DIP and verify its integrity */
Amit Blaydf42d2f2015-02-03 16:37:09 +0200754static int mdtp_tzbsp_dec_verify_DIP(DIP_t *enc_dip, DIP_t *dec_dip, uint32_t *verified)
Amit Blay6281ebc2015-01-11 14:44:08 +0200755{
Amit Blay6281ebc2015-01-11 14:44:08 +0200756 unsigned char hash[HASH_LEN];
757 SHA256_CTX sha256_ctx;
758 int ret;
759
760 ASSERT(enc_dip != NULL);
761 ASSERT(dec_dip != NULL);
762 ASSERT(verified != NULL);
763
Amit Blay4418fb42015-05-05 08:45:13 +0300764 arch_clean_invalidate_cache_range((addr_t)enc_dip, sizeof(DIP_t));
765 arch_invalidate_cache_range((addr_t)dec_dip, sizeof(DIP_t));
766
Amit Blay6281ebc2015-01-11 14:44:08 +0200767 ret = mdtp_cipher_dip_cmd((uint8_t*)enc_dip, sizeof(DIP_t),
768 (uint8_t*)dec_dip, sizeof(DIP_t),
769 DIP_DECRYPT);
770 if (ret)
771 {
772 dprintf(CRITICAL, "mdtp: mdtp_tzbsp_dec_verify_DIP: ERROR, cannot cipher DIP\n");
773 *verified = 0;
Amit Blay8e2731c2015-04-28 21:54:55 +0300774 memset(dec_dip, 0, sizeof(DIP_t));
Amit Blay6281ebc2015-01-11 14:44:08 +0200775 return -1;
776 }
777
Amit Blay4418fb42015-05-05 08:45:13 +0300778 arch_invalidate_cache_range((addr_t)dec_dip, sizeof(DIP_t));
779
Amit Blay6281ebc2015-01-11 14:44:08 +0200780 SHA256_Init(&sha256_ctx);
781 SHA256_Update(&sha256_ctx, dec_dip, sizeof(DIP_t) - HASH_LEN);
782 SHA256_Final(hash, &sha256_ctx);
783
Amit Blay8e2731c2015-04-28 21:54:55 +0300784 if (memcmp(hash, dec_dip->hash, HASH_LEN))
Amit Blay6281ebc2015-01-11 14:44:08 +0200785 {
786 *verified = 0;
Amit Blay8e2731c2015-04-28 21:54:55 +0300787 memset(dec_dip, 0, sizeof(DIP_t));
Amit Blay6281ebc2015-01-11 14:44:08 +0200788 }
789 else
790 {
791 *verified = 1;
792 }
793
794 return 0;
795}
796
Amit Blay4aa292f2015-04-28 21:55:59 +0300797/* Encrypt a given DIP and calculate its integrity information */
Amit Blaydf42d2f2015-02-03 16:37:09 +0200798static int mdtp_tzbsp_enc_hash_DIP(DIP_t *dec_dip, DIP_t *enc_dip)
Amit Blay6281ebc2015-01-11 14:44:08 +0200799{
Amit Blay6281ebc2015-01-11 14:44:08 +0200800 SHA256_CTX sha256_ctx;
801 int ret;
802
803 ASSERT(dec_dip != NULL);
804 ASSERT(enc_dip != NULL);
805
Amit Blay6281ebc2015-01-11 14:44:08 +0200806 SHA256_Init(&sha256_ctx);
807 SHA256_Update(&sha256_ctx, dec_dip, sizeof(DIP_t) - HASH_LEN);
Amit Blay8e2731c2015-04-28 21:54:55 +0300808 SHA256_Final(dec_dip->hash, &sha256_ctx);
Amit Blay6281ebc2015-01-11 14:44:08 +0200809
Amit Blay4418fb42015-05-05 08:45:13 +0300810 arch_clean_invalidate_cache_range((addr_t)dec_dip, sizeof(DIP_t));
811 arch_invalidate_cache_range((addr_t)enc_dip, sizeof(DIP_t));
812
Amit Blay6281ebc2015-01-11 14:44:08 +0200813 ret = mdtp_cipher_dip_cmd((uint8_t*)dec_dip, sizeof(DIP_t),
814 (uint8_t*)enc_dip, sizeof(DIP_t),
815 DIP_ENCRYPT);
816 if (ret)
817 {
818 dprintf(CRITICAL, "mdtp: mdtp_tzbsp_enc_hash_DIP: ERROR, cannot cipher DIP\n");
819 return -1;
820 }
821
Amit Blay4418fb42015-05-05 08:45:13 +0300822 arch_invalidate_cache_range((addr_t)enc_dip, sizeof(DIP_t));
823
Amit Blay6281ebc2015-01-11 14:44:08 +0200824 return 0;
825}
Amit Blay4aa292f2015-04-28 21:55:59 +0300826
827/* Disallow the CIPHER_DIP SCM call */
828static void mdtp_tzbsp_disallow_cipher_DIP(void)
829{
830 DIP_t *dip;
831 int i;
832
833 dip = malloc(sizeof(DIP_t));
834 if (dip == NULL)
835 {
836 dprintf(CRITICAL, "mdtp: mdtp_tzbsp_disallow_cipher_DIP: ERROR, cannot allocate DIP\n");
837 return;
838 }
839
840 /* Disallow the CIPHER_DIP SCM by calling it MAX_CIPHER_DIP_SCM_CALLS times */
841 for (i=0; i<MAX_CIPHER_DIP_SCM_CALLS; i++)
842 {
843 mdtp_tzbsp_enc_hash_DIP(dip, dip);
844 }
845
846 free(dip);
847}