blob: 70e8be238af8831e61b57df92ff1cea2cf7002cf [file] [log] [blame]
lijuangc2676752018-05-15 13:52:36 +08001/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
Amit Blay6281ebc2015-01-11 14:44:08 +02002 *
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>
Reut Zysman3f3eccd2016-04-20 22:05:36 +030043#include <qtimer.h>
Amit Blay6281ebc2015-01-11 14:44:08 +020044#include "scm.h"
45#include "mdtp.h"
Reut Zysmanff6bab92016-02-09 14:06:31 +020046#include "mdtp_fs.h"
47
Amit Blay6281ebc2015-01-11 14:44:08 +020048
Amit Blay4aa292f2015-04-28 21:55:59 +030049#define DIP_ENCRYPT (0)
50#define DIP_DECRYPT (1)
51#define MAX_CIPHER_DIP_SCM_CALLS (3)
Amit Blay6281ebc2015-01-11 14:44:08 +020052
Amit Blay8e2731c2015-04-28 21:54:55 +030053#define MDTP_MAJOR_VERSION (0)
54#define MDTP_MINOR_VERSION (2)
55
Reut Zysmand7138622016-01-18 14:43:59 +020056#define MDTP_CORRECT_PIN_DELAY_MSEC (1000)
57
Amit Blay8e2731c2015-04-28 21:54:55 +030058/** Extract major version number from complete version. */
59#define MDTP_GET_MAJOR_VERSION(version) ((version) >> 16)
60
Amir Kotzerbb8be142016-02-23 09:38:25 +020061
62/** UT defines **/
63#define BAD_PARAM_SIZE 0
64#define BAD_PARAM_VERIF_RATIO 101
65#define BAD_HASH_MODE 10
66
67/********************************************************************************/
68
Amit Blaydf42d2f2015-02-03 16:37:09 +020069static int mdtp_tzbsp_dec_verify_DIP(DIP_t *enc_dip, DIP_t *dec_dip, uint32_t *verified);
70static int mdtp_tzbsp_enc_hash_DIP(DIP_t *dec_dip, DIP_t *enc_dip);
Amit Blay4aa292f2015-04-28 21:55:59 +030071static void mdtp_tzbsp_disallow_cipher_DIP(void);
Amit Blay6281ebc2015-01-11 14:44:08 +020072
Amit Blay8e2731c2015-04-28 21:54:55 +030073uint32_t g_mdtp_version = (((MDTP_MAJOR_VERSION << 16) & 0xFFFF0000) | (MDTP_MINOR_VERSION & 0x0000FFFF));
Amit Blay4aa292f2015-04-28 21:55:59 +030074static int is_mdtp_activated = -1;
Amit Blay8e2731c2015-04-28 21:54:55 +030075
Vijay Kumar Pendoti9c002ad2016-03-09 13:52:45 +053076extern int check_aboot_addr_range_overlap(uintptr_t start, uint32_t size);
Rami Butsteinfaecf7f2015-06-04 16:39:30 +030077void free_mdtp_image(void);
Amit Blay8e2731c2015-04-28 21:54:55 +030078
Amit Blay6281ebc2015-01-11 14:44:08 +020079/********************************************************************************/
80
81/* Read the DIP from EMMC */
Amit Blaydf42d2f2015-02-03 16:37:09 +020082static int read_DIP(DIP_t *dip)
Amit Blay6281ebc2015-01-11 14:44:08 +020083{
84 unsigned long long ptn = 0;
85 uint32_t actual_partition_size;
Amit Blaydf42d2f2015-02-03 16:37:09 +020086 uint32_t block_size = mmc_get_device_blocksize();
Amit Blay6281ebc2015-01-11 14:44:08 +020087
88 int index = INVALID_PTN;
89
90 ASSERT(dip != NULL);
91
92 index = partition_get_index("dip");
93 ptn = partition_get_offset(index);
94
95 if(ptn == 0)
96 {
97 return -1;
98 }
99
100 actual_partition_size = ROUNDUP(sizeof(DIP_t), block_size);
101
102 if(mmc_read(ptn, (void *)dip, actual_partition_size))
103 {
104 dprintf(CRITICAL, "mdtp: read_DIP: ERROR, cannot read DIP info\n");
105 return -1;
106 }
107
Reut Zysman18411272015-02-09 13:47:27 +0200108 dprintf(SPEW, "mdtp: read_DIP: SUCCESS, read %d bytes\n", actual_partition_size);
Amit Blay6281ebc2015-01-11 14:44:08 +0200109
110 return 0;
111}
112
113/* Store the DIP into the EMMC */
Amit Blaydf42d2f2015-02-03 16:37:09 +0200114static int write_DIP(DIP_t *dip)
Amit Blay6281ebc2015-01-11 14:44:08 +0200115{
116 unsigned long long ptn = 0;
Amit Blaydf42d2f2015-02-03 16:37:09 +0200117 uint32_t block_size = mmc_get_device_blocksize();
Amit Blay6281ebc2015-01-11 14:44:08 +0200118
119 int index = INVALID_PTN;
120
121 ASSERT(dip != NULL);
122
123 index = partition_get_index("dip");
124 ptn = partition_get_offset(index);
Reut Zysman18411272015-02-09 13:47:27 +0200125
Amit Blay6281ebc2015-01-11 14:44:08 +0200126 if(ptn == 0)
127 {
128 return -1;
129 }
130
Reut Zysman18411272015-02-09 13:47:27 +0200131 if(mmc_write(ptn, ROUNDUP(sizeof(DIP_t), block_size), (void *)dip))
Amit Blay6281ebc2015-01-11 14:44:08 +0200132 {
Amit Blay8e2731c2015-04-28 21:54:55 +0300133 dprintf(CRITICAL, "mdtp: write_DIP: ERROR, cannot write DIP info\n");
Amit Blay6281ebc2015-01-11 14:44:08 +0200134 return -1;
135 }
136
Reut Zysman18411272015-02-09 13:47:27 +0200137 dprintf(SPEW, "mdtp: write_DIP: SUCCESS, write %d bytes\n", ROUNDUP(sizeof(DIP_t), block_size));
138
Amit Blay6281ebc2015-01-11 14:44:08 +0200139 return 0;
140}
141
Reut Zysman18411272015-02-09 13:47:27 +0200142/* Deactivate MDTP by storing the default DIP into the EMMC */
143static void write_deactivated_DIP()
Amit Blay6281ebc2015-01-11 14:44:08 +0200144{
Amit Blaydf42d2f2015-02-03 16:37:09 +0200145 DIP_t *enc_dip;
146 DIP_t *dec_dip;
Amit Blay6281ebc2015-01-11 14:44:08 +0200147 int ret;
148
149 enc_dip = malloc(sizeof(DIP_t));
150 if (enc_dip == NULL)
151 {
Reut Zysman18411272015-02-09 13:47:27 +0200152 dprintf(CRITICAL, "mdtp: write_deactivated_DIP: ERROR, cannot allocate DIP\n");
Amit Blay6281ebc2015-01-11 14:44:08 +0200153 return;
154 }
155
156 dec_dip = malloc(sizeof(DIP_t));
157 if (dec_dip == NULL)
158 {
Reut Zysman18411272015-02-09 13:47:27 +0200159 dprintf(CRITICAL, "mdtp: write_deactivated_DIP: ERROR, cannot allocate DIP\n");
Amit Blay6281ebc2015-01-11 14:44:08 +0200160 free(enc_dip);
161 return;
162 }
163
164 memset(dec_dip, 0, sizeof(DIP_t));
165
166 dec_dip->status = DIP_STATUS_DEACTIVATED;
Amit Blay8e2731c2015-04-28 21:54:55 +0300167 dec_dip->version = g_mdtp_version;
Amit Blay6281ebc2015-01-11 14:44:08 +0200168
169 ret = mdtp_tzbsp_enc_hash_DIP(dec_dip, enc_dip);
170 if(ret < 0)
171 {
Reut Zysman18411272015-02-09 13:47:27 +0200172 dprintf(CRITICAL, "mdtp: write_deactivated_DIP: ERROR, cannot cipher DIP\n");
Amit Blay6281ebc2015-01-11 14:44:08 +0200173 goto out;
174 }
175
176 ret = write_DIP(enc_dip);
177 if(ret < 0)
178 {
Reut Zysman18411272015-02-09 13:47:27 +0200179 dprintf(CRITICAL, "mdtp: write_deactivated_DIP: ERROR, cannot write DIP\n");
Amit Blay6281ebc2015-01-11 14:44:08 +0200180 goto out;
181 }
182
183out:
184 free(enc_dip);
185 free(dec_dip);
186}
187
188/* Validate a hash calculated on entire given partition */
Amit Blay8e2731c2015-04-28 21:54:55 +0300189static int verify_partition_single_hash(char *name, uint64_t size, DIP_hash_table_entry_t *hash_table)
Amit Blay6281ebc2015-01-11 14:44:08 +0200190{
Amit Blay8e2731c2015-04-28 21:54:55 +0300191 unsigned char digest[HASH_LEN]={0};
Amit Blay6281ebc2015-01-11 14:44:08 +0200192 unsigned long long ptn = 0;
193 int index = INVALID_PTN;
Amit Blay4aa292f2015-04-28 21:55:59 +0300194 unsigned char *buf = (unsigned char *)target_get_scratch_address() + MDTP_SCRATCH_OFFSET;
Amit Blaydf42d2f2015-02-03 16:37:09 +0200195 uint32_t block_size = mmc_get_device_blocksize();
Amit Blay8e2731c2015-04-28 21:54:55 +0300196 uint64_t actual_partition_size = ROUNDUP(size, block_size);
Amit Blay6281ebc2015-01-11 14:44:08 +0200197
Amit Blay8e2731c2015-04-28 21:54:55 +0300198 dprintf(SPEW, "mdtp: verify_partition_single_hash: %s, %llu\n", name, size);
Amit Blay6281ebc2015-01-11 14:44:08 +0200199
200 ASSERT(name != NULL);
201 ASSERT(hash_table != NULL);
Amit Blay8e2731c2015-04-28 21:54:55 +0300202 ASSERT(size > 0);
Amit Blay6281ebc2015-01-11 14:44:08 +0200203
204 index = partition_get_index(name);
205 ptn = partition_get_offset(index);
206
207 if(ptn == 0) {
208 dprintf(CRITICAL, "mdtp: verify_partition_single_hash: %s: partition was not found\n", name);
209 return -1;
210 }
211
Amit Blay6281ebc2015-01-11 14:44:08 +0200212 if (mmc_read(ptn, (void *)buf, actual_partition_size))
213 {
Amit Blay8e2731c2015-04-28 21:54:55 +0300214 dprintf(CRITICAL, "mdtp: verify_partition_single_hash: %s: mmc_read() fail.\n", name);
Amit Blay6281ebc2015-01-11 14:44:08 +0200215 return -1;
216 }
217
Amit Blayfe649212015-01-25 11:21:10 +0200218 /* calculating the hash value using HW crypto */
219 target_crypto_init_params();
Reut Zysmanff6bab92016-02-09 14:06:31 +0200220
221 if(strcmp(name, "mdtp") == 0){
222 buf[0] = 0; // removes first byte
223 dprintf(INFO, "mdtp: verify_partition_single_hash: removes 1st byte\n");
224 }
225
Amit Blay8e2731c2015-04-28 21:54:55 +0300226 hash_find(buf, size, digest, CRYPTO_AUTH_ALG_SHA256);
Amit Blay6281ebc2015-01-11 14:44:08 +0200227
Amit Blay8e2731c2015-04-28 21:54:55 +0300228 if (memcmp(digest, hash_table->hash, HASH_LEN))
Amit Blay6281ebc2015-01-11 14:44:08 +0200229 {
230 dprintf(CRITICAL, "mdtp: verify_partition_single_hash: %s: Failed partition hash verification\n", name);
231
232 return -1;
233 }
234
Reut Zysman18411272015-02-09 13:47:27 +0200235 dprintf(SPEW, "verify_partition_single_hash: %s: VERIFIED!\n", name);
Amit Blay6281ebc2015-01-11 14:44:08 +0200236
237 return 0;
238}
239
240/* Validate a hash table calculated per block of a given partition */
Amit Blaydf42d2f2015-02-03 16:37:09 +0200241static int verify_partition_block_hash(char *name,
Reut Zysman3f3eccd2016-04-20 22:05:36 +0300242 uint64_t size,
243 uint32_t verify_num_blocks,
244 DIP_hash_table_entry_t *hash_table,
245 uint8_t *force_verify_block)
Amit Blay6281ebc2015-01-11 14:44:08 +0200246{
Amit Blay8e2731c2015-04-28 21:54:55 +0300247 unsigned char digest[HASH_LEN]={0};
Amit Blay6281ebc2015-01-11 14:44:08 +0200248 unsigned long long ptn = 0;
249 int index = INVALID_PTN;
Amit Blay4aa292f2015-04-28 21:55:59 +0300250 unsigned char *buf = (unsigned char *)target_get_scratch_address() + MDTP_SCRATCH_OFFSET;
Amit Blay6281ebc2015-01-11 14:44:08 +0200251 uint32_t bytes_to_read;
252 uint32_t block_num = 0;
Amit Blay8e2731c2015-04-28 21:54:55 +0300253 uint32_t total_num_blocks = ((size - 1) / MDTP_FWLOCK_BLOCK_SIZE) + 1;
254 uint32_t rand_int;
255 uint32_t block_size = mmc_get_device_blocksize();
Amit Blay6281ebc2015-01-11 14:44:08 +0200256
Amit Blay8e2731c2015-04-28 21:54:55 +0300257 dprintf(SPEW, "mdtp: verify_partition_block_hash: %s, %llu\n", name, size);
Amit Blay6281ebc2015-01-11 14:44:08 +0200258
259 ASSERT(name != NULL);
260 ASSERT(hash_table != NULL);
Amit Blay8e2731c2015-04-28 21:54:55 +0300261 ASSERT(size > 0);
262 ASSERT(force_verify_block != NULL);
Amit Blay6281ebc2015-01-11 14:44:08 +0200263
264 index = partition_get_index(name);
265 ptn = partition_get_offset(index);
266
267 if(ptn == 0) {
268 dprintf(CRITICAL, "mdtp: verify_partition_block_hash: %s: partition was not found\n", name);
269 return -1;
270 }
271
Amit Blayfe649212015-01-25 11:21:10 +0200272 /* initiating parameters for hash calculation using HW crypto */
273 target_crypto_init_params();
Vijay Kumar Pendoti9c002ad2016-03-09 13:52:45 +0530274 if (check_aboot_addr_range_overlap((uintptr_t)buf, ROUNDUP(MDTP_FWLOCK_BLOCK_SIZE, block_size)))
Amit Blay8e2731c2015-04-28 21:54:55 +0300275 {
276 dprintf(CRITICAL, "mdtp: verify_partition_block_hash: %s: image buffer address overlaps with aboot addresses.\n", name);
277 return -1;
278 }
Amit Blayfe649212015-01-25 11:21:10 +0200279
Amit Blay6281ebc2015-01-11 14:44:08 +0200280 while (MDTP_FWLOCK_BLOCK_SIZE * block_num < size)
281 {
282 if (*force_verify_block == 0)
283 {
lijuang0889e192017-12-19 16:29:37 +0800284 if(scm_random((uintptr_t *)&rand_int, sizeof(rand_int)))
Amit Blay8e2731c2015-04-28 21:54:55 +0300285 {
286 dprintf(CRITICAL,"mdtp: scm_call for random failed\n");
287 return -1;
288 }
289
Amit Blay6281ebc2015-01-11 14:44:08 +0200290 /* Skip validation of this block with probability of verify_num_blocks / total_num_blocks */
Amit Blay8e2731c2015-04-28 21:54:55 +0300291 if ((rand_int % total_num_blocks) >= verify_num_blocks)
Amit Blay6281ebc2015-01-11 14:44:08 +0200292 {
293 block_num++;
294 hash_table += 1;
295 force_verify_block += 1;
296 dprintf(CRITICAL, "mdtp: verify_partition_block_hash: %s: skipped verification of block %d\n", name, block_num);
297 continue;
298 }
299 }
300
Amit Blay6281ebc2015-01-11 14:44:08 +0200301 if ((size - (MDTP_FWLOCK_BLOCK_SIZE * block_num) < MDTP_FWLOCK_BLOCK_SIZE))
302 {
303 bytes_to_read = size - (MDTP_FWLOCK_BLOCK_SIZE * block_num);
304 } else
305 {
306 bytes_to_read = MDTP_FWLOCK_BLOCK_SIZE;
307 }
308
Amit Blay8e2731c2015-04-28 21:54:55 +0300309 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 +0200310 {
311 dprintf(CRITICAL, "mdtp: verify_partition_block_hash: %s: mmc_read() fail.\n", name);
312 return -1;
313 }
314
Amit Blayfe649212015-01-25 11:21:10 +0200315 /* calculating the hash value using HW */
Amit Blay8e2731c2015-04-28 21:54:55 +0300316 hash_find(buf, bytes_to_read, digest, CRYPTO_AUTH_ALG_SHA256);
Amit Blay6281ebc2015-01-11 14:44:08 +0200317
Amit Blay8e2731c2015-04-28 21:54:55 +0300318 if (memcmp(digest, hash_table->hash, HASH_LEN))
Amit Blay6281ebc2015-01-11 14:44:08 +0200319 {
320 dprintf(CRITICAL, "mdtp: verify_partition_block_hash: %s: Failed partition hash[%d] verification\n", name, block_num);
321 return -1;
322 }
323
324 block_num++;
325 hash_table += 1;
326 force_verify_block += 1;
327 }
328
Reut Zysman18411272015-02-09 13:47:27 +0200329 dprintf(SPEW, "verify_partition_block_hash: %s: VERIFIED!\n", name);
Amit Blay6281ebc2015-01-11 14:44:08 +0200330
331 return 0;
332}
333
Amit Blay8e2731c2015-04-28 21:54:55 +0300334/* Validate the partition parameters read from DIP */
335static int validate_partition_params(uint64_t size,
Reut Zysman3f3eccd2016-04-20 22:05:36 +0300336 mdtp_fwlock_mode_t hash_mode,
337 uint32_t verify_ratio)
Amit Blay6281ebc2015-01-11 14:44:08 +0200338{
Amit Blay8e2731c2015-04-28 21:54:55 +0300339 if (size == 0 || size > (uint64_t)MDTP_FWLOCK_BLOCK_SIZE * (uint64_t)MAX_BLOCKS ||
Reut Zysman3f3eccd2016-04-20 22:05:36 +0300340 hash_mode > MDTP_FWLOCK_MODE_FILES || verify_ratio > 100)
Amit Blay6281ebc2015-01-11 14:44:08 +0200341 {
Amit Blay8e2731c2015-04-28 21:54:55 +0300342 dprintf(CRITICAL, "mdtp: validate_partition_params: error, size=%llu, hash_mode=%d, verify_ratio=%d\n",
Reut Zysman3f3eccd2016-04-20 22:05:36 +0300343 size, hash_mode, verify_ratio);
Amit Blay6281ebc2015-01-11 14:44:08 +0200344 return -1;
345 }
346
347 return 0;
348}
349
Amit Blay8e2731c2015-04-28 21:54:55 +0300350/* Verify a given partitinon */
351static int verify_partition(char *name,
Reut Zysman3f3eccd2016-04-20 22:05:36 +0300352 uint64_t size,
353 mdtp_fwlock_mode_t hash_mode,
354 uint32_t verify_num_blocks,
355 DIP_hash_table_entry_t *hash_table,
356 uint8_t *force_verify_block)
Amit Blay8e2731c2015-04-28 21:54:55 +0300357{
358 if (hash_mode == MDTP_FWLOCK_MODE_SINGLE)
359 {
360 return verify_partition_single_hash(name, size, hash_table);
361 } else if (hash_mode == MDTP_FWLOCK_MODE_BLOCK || hash_mode == MDTP_FWLOCK_MODE_FILES)
362 {
363 return verify_partition_block_hash(name, size, verify_num_blocks, hash_table, force_verify_block);
364 }
365
366 /* Illegal value of hash_mode */
367 return -1;
368}
369
370static int validate_dip(DIP_t *dip)
371{
372 uint8_t *dip_p;
373
374 ASSERT(dip != NULL);
375
376 /* Make sure DIP version is supported by current SW */
377 if (MDTP_GET_MAJOR_VERSION(dip->version) != MDTP_MAJOR_VERSION)
378 {
379 dprintf(CRITICAL, "mdtp: validate_dip: Wrong DIP version 0x%x\n", dip->version);
380 return -1;
381 }
382
383 /* Make sure that deactivated DIP content is as expected */
384 if (dip->status == DIP_STATUS_DEACTIVATED)
385 {
386 dip_p = (uint8_t*)&dip->mdtp_cfg;
387 while (dip_p < dip->hash)
388 {
389 if (*dip_p != 0)
390 {
391 dprintf(CRITICAL, "mdtp: validate_dip: error in deactivated DIP\n");
392 return -1;
393 }
394 dip_p++;
395 }
396 }
397
398 return 0;
399}
400
Reut Zysmanff6bab92016-02-09 14:06:31 +0200401/* Display the recovery UI in case mdtp image is corrupted */
402static void display_mdtp_fail_recovery_ui(){
403 display_error_msg_mdtp();
404}
405
Reut Zysman18411272015-02-09 13:47:27 +0200406/* Display the recovery UI to allow the user to enter the PIN and continue boot */
Amit Blay4aa292f2015-04-28 21:55:59 +0300407static void display_recovery_ui(mdtp_cfg_t *mdtp_cfg)
Reut Zysman18411272015-02-09 13:47:27 +0200408{
409 uint32_t pin_length = 0;
Amir Kotzer20716f12016-02-24 10:31:18 +0200410 char entered_pin[MDTP_PIN_LEN+1] = {0};
Reut Zysman18411272015-02-09 13:47:27 +0200411 uint32_t i;
Amir Kotzer3b3217c2016-02-29 17:20:28 +0200412 int pin_mismatch = -1;
Reut Zysman18411272015-02-09 13:47:27 +0200413
Amit Blay4aa292f2015-04-28 21:55:59 +0300414 if (mdtp_cfg->enable_local_pin_authentication)
Reut Zysman18411272015-02-09 13:47:27 +0200415 {
416 dprintf(SPEW, "mdtp: display_recovery_ui: Local deactivation enabled\n");
417
Amit Blay4aa292f2015-04-28 21:55:59 +0300418 pin_length = strlen(mdtp_cfg->mdtp_pin.mdtp_pin);
Reut Zysman18411272015-02-09 13:47:27 +0200419
Amir Kotzer20716f12016-02-24 10:31:18 +0200420 if (pin_length != MDTP_PIN_LEN)
Reut Zysman18411272015-02-09 13:47:27 +0200421 {
422 dprintf(CRITICAL, "mdtp: display_recovery_ui: Error, invalid PIN length\n");
Amit Blay8e2731c2015-04-28 21:54:55 +0300423 display_error_msg(); /* This will never return */
Reut Zysman18411272015-02-09 13:47:27 +0200424 }
425
426 // Set entered_pin to initial '0' string + null terminator
427 for (i=0; i<pin_length; i++)
428 {
429 entered_pin[i] = '0';
430 }
431
432 // Allow the user to enter the PIN as many times as he wishes
433 // (with INVALID_PIN_DELAY_MSECONDS after each failed attempt)
434 while (1)
435 {
Amir Kotzer3b3217c2016-02-29 17:20:28 +0200436 pin_mismatch = pin_length;
Amit Blay8e2731c2015-04-28 21:54:55 +0300437 get_pin_from_user(entered_pin, pin_length);
Reut Zysman18411272015-02-09 13:47:27 +0200438
Amit Blay8e2731c2015-04-28 21:54:55 +0300439 // Go over the entire PIN in any case, to prevent side-channel attacks
440 for (i=0; i<pin_length; i++)
441 {
Amir Kotzer3b3217c2016-02-29 17:20:28 +0200442 // If current digit match, reduce 1 from pin_mismatch
443 pin_mismatch -= (((mdtp_cfg->mdtp_pin.mdtp_pin[i] ^ entered_pin[i]) == 0) ? 1 : 0);
Amit Blay8e2731c2015-04-28 21:54:55 +0300444 }
Reut Zysman18411272015-02-09 13:47:27 +0200445
Amit Blay8e2731c2015-04-28 21:54:55 +0300446 if (0 == pin_mismatch)
447 {
448 // Valid PIN - deactivate and continue boot
449 dprintf(SPEW, "mdtp: display_recovery_ui: valid PIN, continue boot\n");
450 write_deactivated_DIP();
Rami Butsteinfaecf7f2015-06-04 16:39:30 +0300451 goto out;
Amit Blay8e2731c2015-04-28 21:54:55 +0300452 }
453 else
454 {
455 // Invalid PIN - display an appropriate message (which also includes a wait
456 // for INVALID_PIN_DELAY_MSECONDS), and allow the user to try again
457 dprintf(CRITICAL, "mdtp: display_recovery_ui: ERROR, invalid PIN\n");
458 display_invalid_pin_msg();
Amit Blay8e2731c2015-04-28 21:54:55 +0300459 }
Reut Zysman18411272015-02-09 13:47:27 +0200460 }
461 }
462 else
463 {
464 dprintf(CRITICAL, "mdtp: display_recovery_ui: Local deactivation disabled, unable to display recovery UI\n");
Amit Blay8e2731c2015-04-28 21:54:55 +0300465 display_error_msg(); /* This will never return */
Reut Zysman18411272015-02-09 13:47:27 +0200466 }
Rami Butsteinfaecf7f2015-06-04 16:39:30 +0300467
468 out:
Amit Blay54849152015-11-09 15:51:40 +0200469 display_image_on_screen();
Rami Butsteinfaecf7f2015-06-04 16:39:30 +0300470 free_mdtp_image();
Reut Zysmand7138622016-01-18 14:43:59 +0200471 mdelay(MDTP_CORRECT_PIN_DELAY_MSEC);
Reut Zysman18411272015-02-09 13:47:27 +0200472}
473
Amit Blay4aa292f2015-04-28 21:55:59 +0300474/* Verify the boot or recovery partitions using boot_verifier. */
475static int verify_ext_partition(mdtp_ext_partition_verification_t *ext_partition)
476{
477 int ret = 0;
478 bool restore_to_orange = false;
479 unsigned long long ptn = 0;
480 int index = INVALID_PTN;
Monika Singh7d2fc272018-03-16 17:16:01 +0530481 uint32_t bootstate;
Amit Blay4aa292f2015-04-28 21:55:59 +0300482
483 /* If image was already verified in aboot, return its status */
484 if (ext_partition->integrity_state == MDTP_PARTITION_STATE_INVALID)
485 {
486 dprintf(CRITICAL, "mdtp: verify_ext_partition: image %s verified externally and failed.\n",
487 ext_partition->partition == MDTP_PARTITION_BOOT ? "boot" : "recovery");
488 return -1;
489 }
490 else if (ext_partition->integrity_state == MDTP_PARTITION_STATE_VALID)
491 {
492 dprintf(CRITICAL, "mdtp: verify_ext_partition: image %s verified externally succesfully.\n",
493 ext_partition->partition == MDTP_PARTITION_BOOT ? "boot" : "recovery");
494 return 0;
495 }
496
497 /* If image was not verified in aboot, verify it ourselves using boot_verifier. */
498
499 /* 1) Initialize keystore. We don't care about return value which is Verified Boot's state machine state. */
500 boot_verify_keystore_init();
501
502 /* 2) If boot_verifier is ORANGE, it will prevent verifying an image. So
503 * temporarly change boot_verifier state to BOOT_INIT.
504 */
505 if (boot_verify_get_state() == ORANGE)
506 restore_to_orange = true;
507 boot_verify_send_event(BOOT_INIT);
508
509 switch (ext_partition->partition)
510 {
511 case MDTP_PARTITION_BOOT:
512 case MDTP_PARTITION_RECOVERY:
513
514 /* 3) Signature may or may not be at the end of the image. Read the signature if needed. */
515 if (!ext_partition->sig_avail)
516 {
Vijay Kumar Pendoti9c002ad2016-03-09 13:52:45 +0530517 if (check_aboot_addr_range_overlap((uintptr_t)(ext_partition->image_addr + ext_partition->image_size), ext_partition->page_size))
Amit Blay4aa292f2015-04-28 21:55:59 +0300518 {
519 dprintf(CRITICAL, "ERROR: Signature read buffer address overlaps with aboot addresses.\n");
520 return -1;
521 }
522
523 index = partition_get_index(ext_partition->partition == MDTP_PARTITION_BOOT ? "boot" : "recovery");
524 ptn = partition_get_offset(index);
525 if(ptn == 0) {
526 dprintf(CRITICAL, "ERROR: partition %s not found\n",
Reut Zysman3f3eccd2016-04-20 22:05:36 +0300527 ext_partition->partition == MDTP_PARTITION_BOOT ? "boot" : "recovery");
Amit Blay4aa292f2015-04-28 21:55:59 +0300528 return -1;
529 }
530
531 if(mmc_read(ptn + ext_partition->image_size, (void *)(ext_partition->image_addr + ext_partition->image_size), ext_partition->page_size))
532 {
533 dprintf(CRITICAL, "ERROR: Cannot read %s image signature\n",
Reut Zysman3f3eccd2016-04-20 22:05:36 +0300534 ext_partition->partition == MDTP_PARTITION_BOOT ? "boot" : "recovery");
Amit Blay4aa292f2015-04-28 21:55:59 +0300535 return -1;
536 }
537 }
538
539 /* 4) Verify the image using its signature. */
540 ret = boot_verify_image((unsigned char *)ext_partition->image_addr,
541 ext_partition->image_size,
Monika Singh7d2fc272018-03-16 17:16:01 +0530542 ext_partition->partition == MDTP_PARTITION_BOOT ? "/boot" : "/recovery",
543 &bootstate);
Amit Blay4aa292f2015-04-28 21:55:59 +0300544 break;
545
546 default:
547 /* Only boot and recovery are legal here */
548 dprintf(CRITICAL, "ERROR: wrong partition %d\n", ext_partition->partition);
549 return -1;
550 }
551
552 if (ret)
553 {
554 dprintf(INFO, "mdtp: verify_ext_partition: image %s verified succesfully in MDTP.\n",
555 ext_partition->partition == MDTP_PARTITION_BOOT ? "boot" : "recovery");
556 }
557 else
558 {
559 dprintf(CRITICAL, "mdtp: verify_ext_partition: image %s verification failed in MDTP.\n",
560 ext_partition->partition == MDTP_PARTITION_BOOT ? "boot" : "recovery");
561 }
562
563 /* 5) Restore the right boot_verifier state upon exit. */
564 if (restore_to_orange)
565 {
566 boot_verify_send_event(DEV_UNLOCK);
567 }
568
569 return ret ? 0 : -1;
570}
571
Amit Blay6281ebc2015-01-11 14:44:08 +0200572/* Verify all protected partitinons according to the DIP */
Amit Blay4aa292f2015-04-28 21:55:59 +0300573static void verify_all_partitions(DIP_t *dip,
Reut Zysman3f3eccd2016-04-20 22:05:36 +0300574 mdtp_ext_partition_verification_t *ext_partition,
575 verify_result_t *verify_result)
Amit Blay6281ebc2015-01-11 14:44:08 +0200576{
577 int i;
Amit Blay4aa292f2015-04-28 21:55:59 +0300578 int verify_failure = 0;
Reut Zysmanff6bab92016-02-09 14:06:31 +0200579 int verify_temp_result = 0;
Amit Blay4aa292f2015-04-28 21:55:59 +0300580 int ext_partition_verify_failure = 0;
Amit Blay6281ebc2015-01-11 14:44:08 +0200581 uint32_t total_num_blocks;
582
583 ASSERT(dip != NULL);
584 ASSERT(verify_result != NULL);
585
586 *verify_result = VERIFY_FAILED;
587
Amit Blay8e2731c2015-04-28 21:54:55 +0300588 if (validate_dip(dip))
589 {
590 dprintf(CRITICAL, "mdtp: verify_all_partitions: failed DIP validation\n");
591 return;
592 }
593
Amit Blay6281ebc2015-01-11 14:44:08 +0200594 if (dip->status == DIP_STATUS_DEACTIVATED)
595 {
596 *verify_result = VERIFY_SKIPPED;
Amit Blay8e2731c2015-04-28 21:54:55 +0300597 return;
Amit Blay6281ebc2015-01-11 14:44:08 +0200598 }
Amit Blay8e2731c2015-04-28 21:54:55 +0300599 else
Amit Blay6281ebc2015-01-11 14:44:08 +0200600 {
Amit Blay8a510302015-08-17 09:20:01 +0300601 if (ext_partition->partition != MDTP_PARTITION_NONE)
Amit Blay6281ebc2015-01-11 14:44:08 +0200602 {
Amit Blay8a510302015-08-17 09:20:01 +0300603 for(i=0; i<MAX_PARTITIONS; i++)
Amit Blay6281ebc2015-01-11 14:44:08 +0200604 {
Reut Zysmanff6bab92016-02-09 14:06:31 +0200605 verify_temp_result = 0;
Amit Blay8a510302015-08-17 09:20:01 +0300606 if(dip->partition_cfg[i].lock_enabled && dip->partition_cfg[i].size)
Amit Blay8e2731c2015-04-28 21:54:55 +0300607 {
Amit Blay8a510302015-08-17 09:20:01 +0300608 total_num_blocks = ((dip->partition_cfg[i].size - 1) / MDTP_FWLOCK_BLOCK_SIZE);
609 if (validate_partition_params(dip->partition_cfg[i].size,
610 dip->partition_cfg[i].hash_mode,
611 dip->partition_cfg[i].verify_ratio))
612 {
613 dprintf(CRITICAL, "mdtp: verify_all_partitions: Wrong partition parameters\n");
614 verify_failure = TRUE;
615 break;
616 }
Amit Blay6281ebc2015-01-11 14:44:08 +0200617
Reut Zysmanff6bab92016-02-09 14:06:31 +0200618 verify_temp_result |= (verify_partition(dip->partition_cfg[i].name,
Amit Blay8a510302015-08-17 09:20:01 +0300619 dip->partition_cfg[i].size,
620 dip->partition_cfg[i].hash_mode,
621 (dip->partition_cfg[i].verify_ratio * total_num_blocks) / 100,
622 dip->partition_cfg[i].hash_table,
623 dip->partition_cfg[i].force_verify_block) != 0);
Reut Zysmanff6bab92016-02-09 14:06:31 +0200624
625 if((verify_temp_result) && (strcmp("mdtp",dip->partition_cfg[i].name) == 0)){
626 *verify_result = VERIFY_MDTP_FAILED;
627 }
628
629 verify_failure |= verify_temp_result;
Amit Blay8a510302015-08-17 09:20:01 +0300630 }
631 }
632
633 ext_partition_verify_failure = verify_ext_partition(ext_partition);
634
635 if (verify_failure || ext_partition_verify_failure)
636 {
637 dprintf(CRITICAL, "mdtp: verify_all_partitions: Failed partition verification\n");
638 return;
Amit Blay6281ebc2015-01-11 14:44:08 +0200639 }
640 }
Shay Nachmanibc10dfe2015-02-10 14:45:55 +0200641 is_mdtp_activated = 1;
Amit Blay6281ebc2015-01-11 14:44:08 +0200642 }
643
644 *verify_result = VERIFY_OK;
Amit Blay8e2731c2015-04-28 21:54:55 +0300645 return;
Amit Blay6281ebc2015-01-11 14:44:08 +0200646}
647
648/* Verify the DIP and all protected partitions */
Amit Blay4aa292f2015-04-28 21:55:59 +0300649static void validate_DIP_and_firmware(mdtp_ext_partition_verification_t *ext_partition)
Amit Blay6281ebc2015-01-11 14:44:08 +0200650{
651 int ret;
Amit Blaydf42d2f2015-02-03 16:37:09 +0200652 DIP_t *enc_dip;
653 DIP_t *dec_dip;
Amit Blay6281ebc2015-01-11 14:44:08 +0200654 uint32_t verified = 0;
655 verify_result_t verify_result;
Amit Blaydf42d2f2015-02-03 16:37:09 +0200656 uint32_t block_size = mmc_get_device_blocksize();
Amit Blay4aa292f2015-04-28 21:55:59 +0300657 mdtp_cfg_t mdtp_cfg;
Amit Blay6281ebc2015-01-11 14:44:08 +0200658
lijuangc2676752018-05-15 13:52:36 +0800659 enc_dip = memalign(CACHE_LINE, ROUNDUP(sizeof(DIP_t), block_size));
Amit Blay6281ebc2015-01-11 14:44:08 +0200660 if (enc_dip == NULL)
661 {
Reut Zysman18411272015-02-09 13:47:27 +0200662 dprintf(CRITICAL, "mdtp: validate_DIP_and_firmware: ERROR, cannot allocate DIP\n");
Amit Blay8e2731c2015-04-28 21:54:55 +0300663 display_error_msg(); /* This will never return */
Amit Blay6281ebc2015-01-11 14:44:08 +0200664 }
665
lijuangc2676752018-05-15 13:52:36 +0800666 dec_dip = memalign(CACHE_LINE, ROUNDUP(sizeof(DIP_t), block_size));
Amit Blay6281ebc2015-01-11 14:44:08 +0200667 if (dec_dip == NULL)
668 {
Reut Zysman18411272015-02-09 13:47:27 +0200669 dprintf(CRITICAL, "mdtp: validate_DIP_and_firmware: ERROR, cannot allocate DIP\n");
Amit Blay6281ebc2015-01-11 14:44:08 +0200670 free(enc_dip);
Amit Blay8e2731c2015-04-28 21:54:55 +0300671 display_error_msg(); /* This will never return */
Amit Blay6281ebc2015-01-11 14:44:08 +0200672 }
673
674 /* Read the DIP holding the MDTP Firmware Lock state from the DIP partition */
675 ret = read_DIP(enc_dip);
676 if(ret < 0)
677 {
678 dprintf(CRITICAL, "mdtp: validate_DIP_and_firmware: ERROR, cannot read DIP\n");
Amit Blay8e2731c2015-04-28 21:54:55 +0300679 display_error_msg(); /* This will never return */
Amit Blay6281ebc2015-01-11 14:44:08 +0200680 }
681
682 /* Decrypt and verify the integrity of the DIP */
683 ret = mdtp_tzbsp_dec_verify_DIP(enc_dip, dec_dip, &verified);
684 if(ret < 0)
685 {
686 dprintf(CRITICAL, "mdtp: validate_DIP_and_firmware: ERROR, cannot verify DIP\n");
Amit Blay8e2731c2015-04-28 21:54:55 +0300687 display_error_msg(); /* This will never return */
Amit Blay6281ebc2015-01-11 14:44:08 +0200688 }
689
690 /* In case DIP integrity verification fails, notify the user and halt */
691 if(!verified)
692 {
693 dprintf(CRITICAL, "mdtp: validate_DIP_and_firmware: ERROR, corrupted DIP\n");
Amit Blay8e2731c2015-04-28 21:54:55 +0300694 display_error_msg(); /* This will never return */
Amit Blay6281ebc2015-01-11 14:44:08 +0200695 }
696
Amit Blay4aa292f2015-04-28 21:55:59 +0300697 /* Verify the integrity of the partitions which are protected, according to the content of the DIP */
698 verify_all_partitions(dec_dip, ext_partition, &verify_result);
699
700 mdtp_cfg = dec_dip->mdtp_cfg;
Amit Blay8e2731c2015-04-28 21:54:55 +0300701
702 /* Clear decrypted DIP since we don't need it anymore */
703 memset(dec_dip, 0, sizeof(DIP_t));
Amit Blay6281ebc2015-01-11 14:44:08 +0200704
Amit Blay4aa292f2015-04-28 21:55:59 +0300705
Amit Blay6281ebc2015-01-11 14:44:08 +0200706 if (verify_result == VERIFY_OK)
707 {
Reut Zysman18411272015-02-09 13:47:27 +0200708 dprintf(SPEW, "mdtp: validate_DIP_and_firmware: Verify OK\n");
Amit Blay6281ebc2015-01-11 14:44:08 +0200709 }
Amit Blay8e2731c2015-04-28 21:54:55 +0300710 else if (verify_result == VERIFY_SKIPPED)
711 {
712 dprintf(SPEW, "mdtp: validate_DIP_and_firmware: Verify skipped\n");
Reut Zysmanff6bab92016-02-09 14:06:31 +0200713 }
714 else if(verify_result == VERIFY_MDTP_FAILED)
715 {
716 dprintf(CRITICAL, "mdtp: validate_DIP_and_firmware: ERROR, corrupted mdtp image\n");
717 display_mdtp_fail_recovery_ui();
718 }
719 else /* VERIFY_FAILED */
Amit Blay6281ebc2015-01-11 14:44:08 +0200720 {
721 dprintf(CRITICAL, "mdtp: validate_DIP_and_firmware: ERROR, corrupted firmware\n");
Amit Blay4aa292f2015-04-28 21:55:59 +0300722 display_recovery_ui(&mdtp_cfg);
Amit Blay6281ebc2015-01-11 14:44:08 +0200723 }
724
Amit Blay4aa292f2015-04-28 21:55:59 +0300725 memset(&mdtp_cfg, 0, sizeof(mdtp_cfg));
726
Amit Blay6281ebc2015-01-11 14:44:08 +0200727 free(enc_dip);
728 free(dec_dip);
729
730 return;
731}
732
Reut Zysmanff6bab92016-02-09 14:06:31 +0200733
Amit Blay6281ebc2015-01-11 14:44:08 +0200734/********************************************************************************/
735
Amit Blay4aa292f2015-04-28 21:55:59 +0300736/** Entry point of the MDTP Firmware Lock.
737 * If needed, verify the DIP and all protected partitions.
738 * Allow passing information about partition verified using an external method
739 * (either boot or recovery). For boot and recovery, either use aboot's
740 * verification result, or use boot_verifier APIs to verify internally.
741 **/
742void mdtp_fwlock_verify_lock(mdtp_ext_partition_verification_t *ext_partition)
Amit Blay6281ebc2015-01-11 14:44:08 +0200743{
Amit Blaydf42d2f2015-02-03 16:37:09 +0200744 int ret;
745 bool enabled;
Amit Blay6281ebc2015-01-11 14:44:08 +0200746
Reut Zysmanff6bab92016-02-09 14:06:31 +0200747 if(mdtp_fs_init() != 0){
748 dprintf(CRITICAL, "mdtp: mdtp_img: ERROR, image file could not be loaded\n");
749 display_error_msg_mdtp(); /* This will never return */
750 }
Shay Nachmanibc10dfe2015-02-10 14:45:55 +0200751 /* sets the default value of this global to be MDTP not activated */
752 is_mdtp_activated = 0;
753
Amit Blay4aa292f2015-04-28 21:55:59 +0300754 do {
755 if (ext_partition == NULL)
756 {
757 dprintf(CRITICAL, "mdtp: mdtp_fwlock_verify_lock: ERROR, external partition is NULL\n");
758 display_error_msg(); /* This will never return */
759 break;
760 }
Amit Blay6281ebc2015-01-11 14:44:08 +0200761
Amit Blay4aa292f2015-04-28 21:55:59 +0300762 ret = mdtp_fuse_get_enabled(&enabled);
763 if(ret)
764 {
765 dprintf(CRITICAL, "mdtp: mdtp_fwlock_verify_lock: ERROR, cannot get enabled fuse\n");
766 display_error_msg(); /* This will never return */
767 }
768
769 /* Continue with Firmware Lock verification only if enabled by eFuse */
770 if (enabled)
771 {
772 /* This function will handle firmware verification failure via UI */
773 validate_DIP_and_firmware(ext_partition);
774 }
775 } while (0);
776
777 /* Disallow CIPHER_DIP SCM call from this point, unless we are in recovery */
778 /* The recovery image will disallow CIPHER_DIP SCM call by itself. */
Amit Blay8a510302015-08-17 09:20:01 +0300779 if (ext_partition->partition == MDTP_PARTITION_BOOT)
Amit Blay6281ebc2015-01-11 14:44:08 +0200780 {
Amit Blay4aa292f2015-04-28 21:55:59 +0300781 mdtp_tzbsp_disallow_cipher_DIP();
Amit Blay6281ebc2015-01-11 14:44:08 +0200782 }
Amit Blay6281ebc2015-01-11 14:44:08 +0200783}
Shay Nachmanibc10dfe2015-02-10 14:45:55 +0200784/********************************************************************************/
785
786/** Indicates whether the MDTP is currently in ACTIVATED state **/
787int mdtp_activated(bool * activated){
788 if(is_mdtp_activated < 0){
789 /* mdtp_fwlock_verify_lock was not called before, the value is not valid */
790 return is_mdtp_activated;
791 }
792
793 *activated = is_mdtp_activated;
794 return 0;
795}
Amit Blay6281ebc2015-01-11 14:44:08 +0200796
797/********************************************************************************/
798
Amit Blay6281ebc2015-01-11 14:44:08 +0200799/* Decrypt a given DIP and verify its integrity */
Amit Blaydf42d2f2015-02-03 16:37:09 +0200800static int mdtp_tzbsp_dec_verify_DIP(DIP_t *enc_dip, DIP_t *dec_dip, uint32_t *verified)
Amit Blay6281ebc2015-01-11 14:44:08 +0200801{
Amit Blay6281ebc2015-01-11 14:44:08 +0200802 unsigned char hash[HASH_LEN];
803 SHA256_CTX sha256_ctx;
804 int ret;
805
806 ASSERT(enc_dip != NULL);
807 ASSERT(dec_dip != NULL);
808 ASSERT(verified != NULL);
809
Amit Blay4418fb42015-05-05 08:45:13 +0300810 arch_clean_invalidate_cache_range((addr_t)enc_dip, sizeof(DIP_t));
811 arch_invalidate_cache_range((addr_t)dec_dip, sizeof(DIP_t));
812
Amit Blay6281ebc2015-01-11 14:44:08 +0200813 ret = mdtp_cipher_dip_cmd((uint8_t*)enc_dip, sizeof(DIP_t),
Reut Zysman3f3eccd2016-04-20 22:05:36 +0300814 (uint8_t*)dec_dip, sizeof(DIP_t),
815 DIP_DECRYPT);
Amit Blay6281ebc2015-01-11 14:44:08 +0200816 if (ret)
817 {
818 dprintf(CRITICAL, "mdtp: mdtp_tzbsp_dec_verify_DIP: ERROR, cannot cipher DIP\n");
819 *verified = 0;
Amit Blay8e2731c2015-04-28 21:54:55 +0300820 memset(dec_dip, 0, sizeof(DIP_t));
Amit Blay6281ebc2015-01-11 14:44:08 +0200821 return -1;
822 }
823
Amit Blay4418fb42015-05-05 08:45:13 +0300824 arch_invalidate_cache_range((addr_t)dec_dip, sizeof(DIP_t));
825
Amit Blay6281ebc2015-01-11 14:44:08 +0200826 SHA256_Init(&sha256_ctx);
827 SHA256_Update(&sha256_ctx, dec_dip, sizeof(DIP_t) - HASH_LEN);
828 SHA256_Final(hash, &sha256_ctx);
829
Amit Blay8e2731c2015-04-28 21:54:55 +0300830 if (memcmp(hash, dec_dip->hash, HASH_LEN))
Amit Blay6281ebc2015-01-11 14:44:08 +0200831 {
832 *verified = 0;
Amit Blay8e2731c2015-04-28 21:54:55 +0300833 memset(dec_dip, 0, sizeof(DIP_t));
Amit Blay6281ebc2015-01-11 14:44:08 +0200834 }
835 else
836 {
837 *verified = 1;
838 }
839
840 return 0;
841}
842
Amit Blay4aa292f2015-04-28 21:55:59 +0300843/* Encrypt a given DIP and calculate its integrity information */
Amit Blaydf42d2f2015-02-03 16:37:09 +0200844static int mdtp_tzbsp_enc_hash_DIP(DIP_t *dec_dip, DIP_t *enc_dip)
Amit Blay6281ebc2015-01-11 14:44:08 +0200845{
Amit Blay6281ebc2015-01-11 14:44:08 +0200846 SHA256_CTX sha256_ctx;
847 int ret;
848
849 ASSERT(dec_dip != NULL);
850 ASSERT(enc_dip != NULL);
851
Amit Blay6281ebc2015-01-11 14:44:08 +0200852 SHA256_Init(&sha256_ctx);
853 SHA256_Update(&sha256_ctx, dec_dip, sizeof(DIP_t) - HASH_LEN);
Amit Blay8e2731c2015-04-28 21:54:55 +0300854 SHA256_Final(dec_dip->hash, &sha256_ctx);
Amit Blay6281ebc2015-01-11 14:44:08 +0200855
Amit Blay4418fb42015-05-05 08:45:13 +0300856 arch_clean_invalidate_cache_range((addr_t)dec_dip, sizeof(DIP_t));
857 arch_invalidate_cache_range((addr_t)enc_dip, sizeof(DIP_t));
858
Amit Blay6281ebc2015-01-11 14:44:08 +0200859 ret = mdtp_cipher_dip_cmd((uint8_t*)dec_dip, sizeof(DIP_t),
Reut Zysman3f3eccd2016-04-20 22:05:36 +0300860 (uint8_t*)enc_dip, sizeof(DIP_t),
861 DIP_ENCRYPT);
Amit Blay6281ebc2015-01-11 14:44:08 +0200862 if (ret)
863 {
864 dprintf(CRITICAL, "mdtp: mdtp_tzbsp_enc_hash_DIP: ERROR, cannot cipher DIP\n");
865 return -1;
866 }
867
Amit Blay4418fb42015-05-05 08:45:13 +0300868 arch_invalidate_cache_range((addr_t)enc_dip, sizeof(DIP_t));
869
Amit Blay6281ebc2015-01-11 14:44:08 +0200870 return 0;
871}
Amit Blay4aa292f2015-04-28 21:55:59 +0300872
873/* Disallow the CIPHER_DIP SCM call */
874static void mdtp_tzbsp_disallow_cipher_DIP(void)
875{
876 DIP_t *dip;
877 int i;
878
879 dip = malloc(sizeof(DIP_t));
880 if (dip == NULL)
881 {
882 dprintf(CRITICAL, "mdtp: mdtp_tzbsp_disallow_cipher_DIP: ERROR, cannot allocate DIP\n");
Amir Kotzer7c768c02016-04-13 09:08:05 +0300883 /* Could not allocate DIP - stop device from booting */
884 display_error_msg(); /* This will never return */
Amit Blay4aa292f2015-04-28 21:55:59 +0300885 }
886
887 /* Disallow the CIPHER_DIP SCM by calling it MAX_CIPHER_DIP_SCM_CALLS times */
888 for (i=0; i<MAX_CIPHER_DIP_SCM_CALLS; i++)
889 {
Reut Zysman3f3eccd2016-04-20 22:05:36 +0300890 mdtp_tzbsp_enc_hash_DIP(dip, dip);
Amit Blay4aa292f2015-04-28 21:55:59 +0300891 }
892
893 free(dip);
894}
Amir Kotzerbb8be142016-02-23 09:38:25 +0200895
896/********************************************************************************/
897
898/** UT functions **/
899
900/** Hashing fuctions UT **/
901int mdtp_verify_hash_ut(){
902 unsigned char digest[HASH_LEN]={0};
903 unsigned int hash_expected_result = 0xD42B0A29;
904 char *buf = "MTDP LK UT hashing functions sanity check";
905 int size = 0;
906 DIP_hash_table_entry_t partition_hash_table;
907 uint8_t partition_force_verify_block = 0;
908
909 char ptr = buf[0];
910 while(ptr){
911 ptr = buf[++size];
912 }
913 //Bad partition name - single mode
914 if(verify_partition_single_hash("BAD_PARTITION", 1, &partition_hash_table) != -1){
915 dprintf(INFO, "verify_hash_ut: [FAIL (1)].\n");
916 return -1;
917 }
918
919 //Bad partition name - block mode
920 if(verify_partition_block_hash("BAD_PARTITION", 1, 1, &partition_hash_table, &partition_force_verify_block) != -1){
921 dprintf(INFO, "verify_hash_ut: [FAIL (2)].\n");
922 return -1;
923 }
924
925 //Hashing sanity check
926 hash_find((unsigned char*)buf, size, digest, CRYPTO_AUTH_ALG_SHA256);
927 unsigned int *hash_res = (unsigned int *)digest;
928 if (*hash_res != hash_expected_result){
929 dprintf(INFO, "verify_hash_ut: [FAIL (3)].\n");
930 return -1;
931 }
932 dprintf(INFO, "verify_hash_ut: [PASS].\n");
933 return 0;
934}
935
936/** Validate partitions params UT **/
937int mdtp_validate_partition_params_ut(){
938 int partition_size = 10;
939 //Bad size
940 if(validate_partition_params(BAD_PARAM_SIZE, MDTP_FWLOCK_MODE_SINGLE, 1) != -1){
941 dprintf(INFO, "validate_partition_params_ut: [FAIL (1)].\n");
942 return -1;
943 }
944
945 //Bad size
946 if(validate_partition_params((uint64_t)MDTP_FWLOCK_BLOCK_SIZE * (uint64_t)MAX_BLOCKS + 1,
Reut Zysman3f3eccd2016-04-20 22:05:36 +0300947 MDTP_FWLOCK_MODE_SINGLE, 1) != -1){
Amir Kotzerbb8be142016-02-23 09:38:25 +0200948 dprintf(INFO, "validate_partition_params_ut: [FAIL (2)].\n");
949 return -1;
950 }
951
952 //Bad verification ratio
953 if(validate_partition_params(partition_size, MDTP_FWLOCK_MODE_SIZE, BAD_PARAM_VERIF_RATIO) != -1){
954 dprintf(INFO, "validate_partition_params_ut: [FAIL (3)].\n");
955 return -1;
956 }
957 dprintf(INFO, "MDTP LK UT: validate_partition_params_ut [ PASS ]\n");
958 return 0;
959}
960
961/** Verify partition UT **/
962int mdtp_verify_partition_ut(){
963 uint8_t partition_force_verify_block = 0;
964 DIP_hash_table_entry_t partition_hash_table;
965 int verify_num_blocks = 10,partition_size = 1;
966
967 //Unkown hashing mode
968 if(verify_partition("system", partition_size, BAD_HASH_MODE, verify_num_blocks,
Reut Zysman3f3eccd2016-04-20 22:05:36 +0300969 &partition_hash_table, &partition_force_verify_block) != -1){
Amir Kotzerbb8be142016-02-23 09:38:25 +0200970 dprintf(INFO, "verify_partition_ut: Failed Test 1.\n");
971 dprintf(INFO, "MDTP LK UT: verify_partition_ut [ FAIL ]\n");
972 return -1;
973 }
974 dprintf(INFO, "MDTP LK UT: verify_partition_ut [ PASS ]\n");
975 return 0;
976}
977