blob: 136fab5ef5c97206c51e8ae7bda1610532ade12f [file] [log] [blame]
Reut Zysmanff6bab92016-02-09 14:06:31 +02001/* Copyright (c) 2015-2016, 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);
Amit Blay4aa292f2015-04-28 21:55:59 +030077int scm_random(uint32_t * rbuf, uint32_t r_len);
Rami Butsteinfaecf7f2015-06-04 16:39:30 +030078void free_mdtp_image(void);
Amit Blay8e2731c2015-04-28 21:54:55 +030079
Amit Blay6281ebc2015-01-11 14:44:08 +020080/********************************************************************************/
81
82/* Read the DIP from EMMC */
Amit Blaydf42d2f2015-02-03 16:37:09 +020083static int read_DIP(DIP_t *dip)
Amit Blay6281ebc2015-01-11 14:44:08 +020084{
85 unsigned long long ptn = 0;
86 uint32_t actual_partition_size;
Amit Blaydf42d2f2015-02-03 16:37:09 +020087 uint32_t block_size = mmc_get_device_blocksize();
Amit Blay6281ebc2015-01-11 14:44:08 +020088
89 int index = INVALID_PTN;
90
91 ASSERT(dip != NULL);
92
93 index = partition_get_index("dip");
94 ptn = partition_get_offset(index);
95
96 if(ptn == 0)
97 {
98 return -1;
99 }
100
101 actual_partition_size = ROUNDUP(sizeof(DIP_t), block_size);
102
103 if(mmc_read(ptn, (void *)dip, actual_partition_size))
104 {
105 dprintf(CRITICAL, "mdtp: read_DIP: ERROR, cannot read DIP info\n");
106 return -1;
107 }
108
Reut Zysman18411272015-02-09 13:47:27 +0200109 dprintf(SPEW, "mdtp: read_DIP: SUCCESS, read %d bytes\n", actual_partition_size);
Amit Blay6281ebc2015-01-11 14:44:08 +0200110
111 return 0;
112}
113
114/* Store the DIP into the EMMC */
Amit Blaydf42d2f2015-02-03 16:37:09 +0200115static int write_DIP(DIP_t *dip)
Amit Blay6281ebc2015-01-11 14:44:08 +0200116{
117 unsigned long long ptn = 0;
Amit Blaydf42d2f2015-02-03 16:37:09 +0200118 uint32_t block_size = mmc_get_device_blocksize();
Amit Blay6281ebc2015-01-11 14:44:08 +0200119
120 int index = INVALID_PTN;
121
122 ASSERT(dip != NULL);
123
124 index = partition_get_index("dip");
125 ptn = partition_get_offset(index);
Reut Zysman18411272015-02-09 13:47:27 +0200126
Amit Blay6281ebc2015-01-11 14:44:08 +0200127 if(ptn == 0)
128 {
129 return -1;
130 }
131
Reut Zysman18411272015-02-09 13:47:27 +0200132 if(mmc_write(ptn, ROUNDUP(sizeof(DIP_t), block_size), (void *)dip))
Amit Blay6281ebc2015-01-11 14:44:08 +0200133 {
Amit Blay8e2731c2015-04-28 21:54:55 +0300134 dprintf(CRITICAL, "mdtp: write_DIP: ERROR, cannot write DIP info\n");
Amit Blay6281ebc2015-01-11 14:44:08 +0200135 return -1;
136 }
137
Reut Zysman18411272015-02-09 13:47:27 +0200138 dprintf(SPEW, "mdtp: write_DIP: SUCCESS, write %d bytes\n", ROUNDUP(sizeof(DIP_t), block_size));
139
Amit Blay6281ebc2015-01-11 14:44:08 +0200140 return 0;
141}
142
Reut Zysman18411272015-02-09 13:47:27 +0200143/* Deactivate MDTP by storing the default DIP into the EMMC */
144static void write_deactivated_DIP()
Amit Blay6281ebc2015-01-11 14:44:08 +0200145{
Amit Blaydf42d2f2015-02-03 16:37:09 +0200146 DIP_t *enc_dip;
147 DIP_t *dec_dip;
Amit Blay6281ebc2015-01-11 14:44:08 +0200148 int ret;
149
150 enc_dip = malloc(sizeof(DIP_t));
151 if (enc_dip == NULL)
152 {
Reut Zysman18411272015-02-09 13:47:27 +0200153 dprintf(CRITICAL, "mdtp: write_deactivated_DIP: ERROR, cannot allocate DIP\n");
Amit Blay6281ebc2015-01-11 14:44:08 +0200154 return;
155 }
156
157 dec_dip = malloc(sizeof(DIP_t));
158 if (dec_dip == NULL)
159 {
Reut Zysman18411272015-02-09 13:47:27 +0200160 dprintf(CRITICAL, "mdtp: write_deactivated_DIP: ERROR, cannot allocate DIP\n");
Amit Blay6281ebc2015-01-11 14:44:08 +0200161 free(enc_dip);
162 return;
163 }
164
165 memset(dec_dip, 0, sizeof(DIP_t));
166
167 dec_dip->status = DIP_STATUS_DEACTIVATED;
Amit Blay8e2731c2015-04-28 21:54:55 +0300168 dec_dip->version = g_mdtp_version;
Amit Blay6281ebc2015-01-11 14:44:08 +0200169
170 ret = mdtp_tzbsp_enc_hash_DIP(dec_dip, enc_dip);
171 if(ret < 0)
172 {
Reut Zysman18411272015-02-09 13:47:27 +0200173 dprintf(CRITICAL, "mdtp: write_deactivated_DIP: ERROR, cannot cipher DIP\n");
Amit Blay6281ebc2015-01-11 14:44:08 +0200174 goto out;
175 }
176
177 ret = write_DIP(enc_dip);
178 if(ret < 0)
179 {
Reut Zysman18411272015-02-09 13:47:27 +0200180 dprintf(CRITICAL, "mdtp: write_deactivated_DIP: ERROR, cannot write DIP\n");
Amit Blay6281ebc2015-01-11 14:44:08 +0200181 goto out;
182 }
183
184out:
185 free(enc_dip);
186 free(dec_dip);
187}
188
189/* Validate a hash calculated on entire given partition */
Amit Blay8e2731c2015-04-28 21:54:55 +0300190static int verify_partition_single_hash(char *name, uint64_t size, DIP_hash_table_entry_t *hash_table)
Amit Blay6281ebc2015-01-11 14:44:08 +0200191{
Amit Blay8e2731c2015-04-28 21:54:55 +0300192 unsigned char digest[HASH_LEN]={0};
Amit Blay6281ebc2015-01-11 14:44:08 +0200193 unsigned long long ptn = 0;
194 int index = INVALID_PTN;
Amit Blay4aa292f2015-04-28 21:55:59 +0300195 unsigned char *buf = (unsigned char *)target_get_scratch_address() + MDTP_SCRATCH_OFFSET;
Amit Blaydf42d2f2015-02-03 16:37:09 +0200196 uint32_t block_size = mmc_get_device_blocksize();
Amit Blay8e2731c2015-04-28 21:54:55 +0300197 uint64_t actual_partition_size = ROUNDUP(size, block_size);
Amit Blay6281ebc2015-01-11 14:44:08 +0200198
Amit Blay8e2731c2015-04-28 21:54:55 +0300199 dprintf(SPEW, "mdtp: verify_partition_single_hash: %s, %llu\n", name, size);
Amit Blay6281ebc2015-01-11 14:44:08 +0200200
201 ASSERT(name != NULL);
202 ASSERT(hash_table != NULL);
Amit Blay8e2731c2015-04-28 21:54:55 +0300203 ASSERT(size > 0);
Amit Blay6281ebc2015-01-11 14:44:08 +0200204
205 index = partition_get_index(name);
206 ptn = partition_get_offset(index);
207
208 if(ptn == 0) {
209 dprintf(CRITICAL, "mdtp: verify_partition_single_hash: %s: partition was not found\n", name);
210 return -1;
211 }
212
Amit Blay6281ebc2015-01-11 14:44:08 +0200213 if (mmc_read(ptn, (void *)buf, actual_partition_size))
214 {
Amit Blay8e2731c2015-04-28 21:54:55 +0300215 dprintf(CRITICAL, "mdtp: verify_partition_single_hash: %s: mmc_read() fail.\n", name);
Amit Blay6281ebc2015-01-11 14:44:08 +0200216 return -1;
217 }
218
Amit Blayfe649212015-01-25 11:21:10 +0200219 /* calculating the hash value using HW crypto */
220 target_crypto_init_params();
Reut Zysmanff6bab92016-02-09 14:06:31 +0200221
222 if(strcmp(name, "mdtp") == 0){
223 buf[0] = 0; // removes first byte
224 dprintf(INFO, "mdtp: verify_partition_single_hash: removes 1st byte\n");
225 }
226
Amit Blay8e2731c2015-04-28 21:54:55 +0300227 hash_find(buf, size, digest, CRYPTO_AUTH_ALG_SHA256);
Amit Blay6281ebc2015-01-11 14:44:08 +0200228
Amit Blay8e2731c2015-04-28 21:54:55 +0300229 if (memcmp(digest, hash_table->hash, HASH_LEN))
Amit Blay6281ebc2015-01-11 14:44:08 +0200230 {
231 dprintf(CRITICAL, "mdtp: verify_partition_single_hash: %s: Failed partition hash verification\n", name);
232
233 return -1;
234 }
235
Reut Zysman18411272015-02-09 13:47:27 +0200236 dprintf(SPEW, "verify_partition_single_hash: %s: VERIFIED!\n", name);
Amit Blay6281ebc2015-01-11 14:44:08 +0200237
238 return 0;
239}
240
241/* Validate a hash table calculated per block of a given partition */
Amit Blaydf42d2f2015-02-03 16:37:09 +0200242static int verify_partition_block_hash(char *name,
Reut Zysman3f3eccd2016-04-20 22:05:36 +0300243 uint64_t size,
244 uint32_t verify_num_blocks,
245 DIP_hash_table_entry_t *hash_table,
246 uint8_t *force_verify_block)
Amit Blay6281ebc2015-01-11 14:44:08 +0200247{
Amit Blay8e2731c2015-04-28 21:54:55 +0300248 unsigned char digest[HASH_LEN]={0};
Amit Blay6281ebc2015-01-11 14:44:08 +0200249 unsigned long long ptn = 0;
250 int index = INVALID_PTN;
Amit Blay4aa292f2015-04-28 21:55:59 +0300251 unsigned char *buf = (unsigned char *)target_get_scratch_address() + MDTP_SCRATCH_OFFSET;
Amit Blay6281ebc2015-01-11 14:44:08 +0200252 uint32_t bytes_to_read;
253 uint32_t block_num = 0;
Amit Blay8e2731c2015-04-28 21:54:55 +0300254 uint32_t total_num_blocks = ((size - 1) / MDTP_FWLOCK_BLOCK_SIZE) + 1;
255 uint32_t rand_int;
256 uint32_t block_size = mmc_get_device_blocksize();
Amit Blay6281ebc2015-01-11 14:44:08 +0200257
Amit Blay8e2731c2015-04-28 21:54:55 +0300258 dprintf(SPEW, "mdtp: verify_partition_block_hash: %s, %llu\n", name, size);
Amit Blay6281ebc2015-01-11 14:44:08 +0200259
260 ASSERT(name != NULL);
261 ASSERT(hash_table != NULL);
Amit Blay8e2731c2015-04-28 21:54:55 +0300262 ASSERT(size > 0);
263 ASSERT(force_verify_block != NULL);
Amit Blay6281ebc2015-01-11 14:44:08 +0200264
265 index = partition_get_index(name);
266 ptn = partition_get_offset(index);
267
268 if(ptn == 0) {
269 dprintf(CRITICAL, "mdtp: verify_partition_block_hash: %s: partition was not found\n", name);
270 return -1;
271 }
272
Amit Blayfe649212015-01-25 11:21:10 +0200273 /* initiating parameters for hash calculation using HW crypto */
274 target_crypto_init_params();
Vijay Kumar Pendoti9c002ad2016-03-09 13:52:45 +0530275 if (check_aboot_addr_range_overlap((uintptr_t)buf, ROUNDUP(MDTP_FWLOCK_BLOCK_SIZE, block_size)))
Amit Blay8e2731c2015-04-28 21:54:55 +0300276 {
277 dprintf(CRITICAL, "mdtp: verify_partition_block_hash: %s: image buffer address overlaps with aboot addresses.\n", name);
278 return -1;
279 }
Amit Blayfe649212015-01-25 11:21:10 +0200280
Amit Blay6281ebc2015-01-11 14:44:08 +0200281 while (MDTP_FWLOCK_BLOCK_SIZE * block_num < size)
282 {
283 if (*force_verify_block == 0)
284 {
Amit Blay8e2731c2015-04-28 21:54:55 +0300285 if(scm_random((uint32_t *)&rand_int, sizeof(rand_int)))
286 {
287 dprintf(CRITICAL,"mdtp: scm_call for random failed\n");
288 return -1;
289 }
290
Amit Blay6281ebc2015-01-11 14:44:08 +0200291 /* Skip validation of this block with probability of verify_num_blocks / total_num_blocks */
Amit Blay8e2731c2015-04-28 21:54:55 +0300292 if ((rand_int % total_num_blocks) >= verify_num_blocks)
Amit Blay6281ebc2015-01-11 14:44:08 +0200293 {
294 block_num++;
295 hash_table += 1;
296 force_verify_block += 1;
297 dprintf(CRITICAL, "mdtp: verify_partition_block_hash: %s: skipped verification of block %d\n", name, block_num);
298 continue;
299 }
300 }
301
Amit Blay6281ebc2015-01-11 14:44:08 +0200302 if ((size - (MDTP_FWLOCK_BLOCK_SIZE * block_num) < MDTP_FWLOCK_BLOCK_SIZE))
303 {
304 bytes_to_read = size - (MDTP_FWLOCK_BLOCK_SIZE * block_num);
305 } else
306 {
307 bytes_to_read = MDTP_FWLOCK_BLOCK_SIZE;
308 }
309
Amit Blay8e2731c2015-04-28 21:54:55 +0300310 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 +0200311 {
312 dprintf(CRITICAL, "mdtp: verify_partition_block_hash: %s: mmc_read() fail.\n", name);
313 return -1;
314 }
315
Amit Blayfe649212015-01-25 11:21:10 +0200316 /* calculating the hash value using HW */
Amit Blay8e2731c2015-04-28 21:54:55 +0300317 hash_find(buf, bytes_to_read, digest, CRYPTO_AUTH_ALG_SHA256);
Amit Blay6281ebc2015-01-11 14:44:08 +0200318
Amit Blay8e2731c2015-04-28 21:54:55 +0300319 if (memcmp(digest, hash_table->hash, HASH_LEN))
Amit Blay6281ebc2015-01-11 14:44:08 +0200320 {
321 dprintf(CRITICAL, "mdtp: verify_partition_block_hash: %s: Failed partition hash[%d] verification\n", name, block_num);
322 return -1;
323 }
324
325 block_num++;
326 hash_table += 1;
327 force_verify_block += 1;
328 }
329
Reut Zysman18411272015-02-09 13:47:27 +0200330 dprintf(SPEW, "verify_partition_block_hash: %s: VERIFIED!\n", name);
Amit Blay6281ebc2015-01-11 14:44:08 +0200331
332 return 0;
333}
334
Amit Blay8e2731c2015-04-28 21:54:55 +0300335/* Validate the partition parameters read from DIP */
336static int validate_partition_params(uint64_t size,
Reut Zysman3f3eccd2016-04-20 22:05:36 +0300337 mdtp_fwlock_mode_t hash_mode,
338 uint32_t verify_ratio)
Amit Blay6281ebc2015-01-11 14:44:08 +0200339{
Amit Blay8e2731c2015-04-28 21:54:55 +0300340 if (size == 0 || size > (uint64_t)MDTP_FWLOCK_BLOCK_SIZE * (uint64_t)MAX_BLOCKS ||
Reut Zysman3f3eccd2016-04-20 22:05:36 +0300341 hash_mode > MDTP_FWLOCK_MODE_FILES || verify_ratio > 100)
Amit Blay6281ebc2015-01-11 14:44:08 +0200342 {
Amit Blay8e2731c2015-04-28 21:54:55 +0300343 dprintf(CRITICAL, "mdtp: validate_partition_params: error, size=%llu, hash_mode=%d, verify_ratio=%d\n",
Reut Zysman3f3eccd2016-04-20 22:05:36 +0300344 size, hash_mode, verify_ratio);
Amit Blay6281ebc2015-01-11 14:44:08 +0200345 return -1;
346 }
347
348 return 0;
349}
350
Amit Blay8e2731c2015-04-28 21:54:55 +0300351/* Verify a given partitinon */
352static int verify_partition(char *name,
Reut Zysman3f3eccd2016-04-20 22:05:36 +0300353 uint64_t size,
354 mdtp_fwlock_mode_t hash_mode,
355 uint32_t verify_num_blocks,
356 DIP_hash_table_entry_t *hash_table,
357 uint8_t *force_verify_block)
Amit Blay8e2731c2015-04-28 21:54:55 +0300358{
359 if (hash_mode == MDTP_FWLOCK_MODE_SINGLE)
360 {
361 return verify_partition_single_hash(name, size, hash_table);
362 } else if (hash_mode == MDTP_FWLOCK_MODE_BLOCK || hash_mode == MDTP_FWLOCK_MODE_FILES)
363 {
364 return verify_partition_block_hash(name, size, verify_num_blocks, hash_table, force_verify_block);
365 }
366
367 /* Illegal value of hash_mode */
368 return -1;
369}
370
371static int validate_dip(DIP_t *dip)
372{
373 uint8_t *dip_p;
374
375 ASSERT(dip != NULL);
376
377 /* Make sure DIP version is supported by current SW */
378 if (MDTP_GET_MAJOR_VERSION(dip->version) != MDTP_MAJOR_VERSION)
379 {
380 dprintf(CRITICAL, "mdtp: validate_dip: Wrong DIP version 0x%x\n", dip->version);
381 return -1;
382 }
383
384 /* Make sure that deactivated DIP content is as expected */
385 if (dip->status == DIP_STATUS_DEACTIVATED)
386 {
387 dip_p = (uint8_t*)&dip->mdtp_cfg;
388 while (dip_p < dip->hash)
389 {
390 if (*dip_p != 0)
391 {
392 dprintf(CRITICAL, "mdtp: validate_dip: error in deactivated DIP\n");
393 return -1;
394 }
395 dip_p++;
396 }
397 }
398
399 return 0;
400}
401
Reut Zysmanff6bab92016-02-09 14:06:31 +0200402/* Display the recovery UI in case mdtp image is corrupted */
403static void display_mdtp_fail_recovery_ui(){
404 display_error_msg_mdtp();
405}
406
Reut Zysman18411272015-02-09 13:47:27 +0200407/* Display the recovery UI to allow the user to enter the PIN and continue boot */
Amit Blay4aa292f2015-04-28 21:55:59 +0300408static void display_recovery_ui(mdtp_cfg_t *mdtp_cfg)
Reut Zysman18411272015-02-09 13:47:27 +0200409{
410 uint32_t pin_length = 0;
Amir Kotzer20716f12016-02-24 10:31:18 +0200411 char entered_pin[MDTP_PIN_LEN+1] = {0};
Reut Zysman18411272015-02-09 13:47:27 +0200412 uint32_t i;
Amir Kotzer3b3217c2016-02-29 17:20:28 +0200413 int pin_mismatch = -1;
Reut Zysman18411272015-02-09 13:47:27 +0200414
Amit Blay4aa292f2015-04-28 21:55:59 +0300415 if (mdtp_cfg->enable_local_pin_authentication)
Reut Zysman18411272015-02-09 13:47:27 +0200416 {
417 dprintf(SPEW, "mdtp: display_recovery_ui: Local deactivation enabled\n");
418
Amit Blay4aa292f2015-04-28 21:55:59 +0300419 pin_length = strlen(mdtp_cfg->mdtp_pin.mdtp_pin);
Reut Zysman18411272015-02-09 13:47:27 +0200420
Amir Kotzer20716f12016-02-24 10:31:18 +0200421 if (pin_length != MDTP_PIN_LEN)
Reut Zysman18411272015-02-09 13:47:27 +0200422 {
423 dprintf(CRITICAL, "mdtp: display_recovery_ui: Error, invalid PIN length\n");
Amit Blay8e2731c2015-04-28 21:54:55 +0300424 display_error_msg(); /* This will never return */
Reut Zysman18411272015-02-09 13:47:27 +0200425 }
426
427 // Set entered_pin to initial '0' string + null terminator
428 for (i=0; i<pin_length; i++)
429 {
430 entered_pin[i] = '0';
431 }
432
433 // Allow the user to enter the PIN as many times as he wishes
434 // (with INVALID_PIN_DELAY_MSECONDS after each failed attempt)
435 while (1)
436 {
Amir Kotzer3b3217c2016-02-29 17:20:28 +0200437 pin_mismatch = pin_length;
Amit Blay8e2731c2015-04-28 21:54:55 +0300438 get_pin_from_user(entered_pin, pin_length);
Reut Zysman18411272015-02-09 13:47:27 +0200439
Amit Blay8e2731c2015-04-28 21:54:55 +0300440 // Go over the entire PIN in any case, to prevent side-channel attacks
441 for (i=0; i<pin_length; i++)
442 {
Amir Kotzer3b3217c2016-02-29 17:20:28 +0200443 // If current digit match, reduce 1 from pin_mismatch
444 pin_mismatch -= (((mdtp_cfg->mdtp_pin.mdtp_pin[i] ^ entered_pin[i]) == 0) ? 1 : 0);
Amit Blay8e2731c2015-04-28 21:54:55 +0300445 }
Reut Zysman18411272015-02-09 13:47:27 +0200446
Amit Blay8e2731c2015-04-28 21:54:55 +0300447 if (0 == pin_mismatch)
448 {
449 // Valid PIN - deactivate and continue boot
450 dprintf(SPEW, "mdtp: display_recovery_ui: valid PIN, continue boot\n");
451 write_deactivated_DIP();
Rami Butsteinfaecf7f2015-06-04 16:39:30 +0300452 goto out;
Amit Blay8e2731c2015-04-28 21:54:55 +0300453 }
454 else
455 {
456 // Invalid PIN - display an appropriate message (which also includes a wait
457 // for INVALID_PIN_DELAY_MSECONDS), and allow the user to try again
458 dprintf(CRITICAL, "mdtp: display_recovery_ui: ERROR, invalid PIN\n");
459 display_invalid_pin_msg();
Amit Blay8e2731c2015-04-28 21:54:55 +0300460 }
Reut Zysman18411272015-02-09 13:47:27 +0200461 }
462 }
463 else
464 {
465 dprintf(CRITICAL, "mdtp: display_recovery_ui: Local deactivation disabled, unable to display recovery UI\n");
Amit Blay8e2731c2015-04-28 21:54:55 +0300466 display_error_msg(); /* This will never return */
Reut Zysman18411272015-02-09 13:47:27 +0200467 }
Rami Butsteinfaecf7f2015-06-04 16:39:30 +0300468
469 out:
Amit Blay54849152015-11-09 15:51:40 +0200470 display_image_on_screen();
Rami Butsteinfaecf7f2015-06-04 16:39:30 +0300471 free_mdtp_image();
Reut Zysmand7138622016-01-18 14:43:59 +0200472 mdelay(MDTP_CORRECT_PIN_DELAY_MSEC);
Reut Zysman18411272015-02-09 13:47:27 +0200473}
474
Amit Blay4aa292f2015-04-28 21:55:59 +0300475/* Verify the boot or recovery partitions using boot_verifier. */
476static int verify_ext_partition(mdtp_ext_partition_verification_t *ext_partition)
477{
478 int ret = 0;
479 bool restore_to_orange = false;
480 unsigned long long ptn = 0;
481 int index = INVALID_PTN;
482
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,
Amit Blay59fad252015-05-17 17:27:17 +0300542 ext_partition->partition == MDTP_PARTITION_BOOT ? "/boot" : "/recovery");
Amit Blay4aa292f2015-04-28 21:55:59 +0300543 break;
544
545 default:
546 /* Only boot and recovery are legal here */
547 dprintf(CRITICAL, "ERROR: wrong partition %d\n", ext_partition->partition);
548 return -1;
549 }
550
551 if (ret)
552 {
553 dprintf(INFO, "mdtp: verify_ext_partition: image %s verified succesfully in MDTP.\n",
554 ext_partition->partition == MDTP_PARTITION_BOOT ? "boot" : "recovery");
555 }
556 else
557 {
558 dprintf(CRITICAL, "mdtp: verify_ext_partition: image %s verification failed in MDTP.\n",
559 ext_partition->partition == MDTP_PARTITION_BOOT ? "boot" : "recovery");
560 }
561
562 /* 5) Restore the right boot_verifier state upon exit. */
563 if (restore_to_orange)
564 {
565 boot_verify_send_event(DEV_UNLOCK);
566 }
567
568 return ret ? 0 : -1;
569}
570
Amit Blay6281ebc2015-01-11 14:44:08 +0200571/* Verify all protected partitinons according to the DIP */
Amit Blay4aa292f2015-04-28 21:55:59 +0300572static void verify_all_partitions(DIP_t *dip,
Reut Zysman3f3eccd2016-04-20 22:05:36 +0300573 mdtp_ext_partition_verification_t *ext_partition,
574 verify_result_t *verify_result)
Amit Blay6281ebc2015-01-11 14:44:08 +0200575{
576 int i;
Amit Blay4aa292f2015-04-28 21:55:59 +0300577 int verify_failure = 0;
Reut Zysmanff6bab92016-02-09 14:06:31 +0200578 int verify_temp_result = 0;
Amit Blay4aa292f2015-04-28 21:55:59 +0300579 int ext_partition_verify_failure = 0;
Amit Blay6281ebc2015-01-11 14:44:08 +0200580 uint32_t total_num_blocks;
581
582 ASSERT(dip != NULL);
583 ASSERT(verify_result != NULL);
584
585 *verify_result = VERIFY_FAILED;
586
Amit Blay8e2731c2015-04-28 21:54:55 +0300587 if (validate_dip(dip))
588 {
589 dprintf(CRITICAL, "mdtp: verify_all_partitions: failed DIP validation\n");
590 return;
591 }
592
Amit Blay6281ebc2015-01-11 14:44:08 +0200593 if (dip->status == DIP_STATUS_DEACTIVATED)
594 {
595 *verify_result = VERIFY_SKIPPED;
Amit Blay8e2731c2015-04-28 21:54:55 +0300596 return;
Amit Blay6281ebc2015-01-11 14:44:08 +0200597 }
Amit Blay8e2731c2015-04-28 21:54:55 +0300598 else
Amit Blay6281ebc2015-01-11 14:44:08 +0200599 {
Amit Blay8a510302015-08-17 09:20:01 +0300600 if (ext_partition->partition != MDTP_PARTITION_NONE)
Amit Blay6281ebc2015-01-11 14:44:08 +0200601 {
Amit Blay8a510302015-08-17 09:20:01 +0300602 for(i=0; i<MAX_PARTITIONS; i++)
Amit Blay6281ebc2015-01-11 14:44:08 +0200603 {
Reut Zysmanff6bab92016-02-09 14:06:31 +0200604 verify_temp_result = 0;
Amit Blay8a510302015-08-17 09:20:01 +0300605 if(dip->partition_cfg[i].lock_enabled && dip->partition_cfg[i].size)
Amit Blay8e2731c2015-04-28 21:54:55 +0300606 {
Amit Blay8a510302015-08-17 09:20:01 +0300607 total_num_blocks = ((dip->partition_cfg[i].size - 1) / MDTP_FWLOCK_BLOCK_SIZE);
608 if (validate_partition_params(dip->partition_cfg[i].size,
609 dip->partition_cfg[i].hash_mode,
610 dip->partition_cfg[i].verify_ratio))
611 {
612 dprintf(CRITICAL, "mdtp: verify_all_partitions: Wrong partition parameters\n");
613 verify_failure = TRUE;
614 break;
615 }
Amit Blay6281ebc2015-01-11 14:44:08 +0200616
Reut Zysmanff6bab92016-02-09 14:06:31 +0200617 verify_temp_result |= (verify_partition(dip->partition_cfg[i].name,
Amit Blay8a510302015-08-17 09:20:01 +0300618 dip->partition_cfg[i].size,
619 dip->partition_cfg[i].hash_mode,
620 (dip->partition_cfg[i].verify_ratio * total_num_blocks) / 100,
621 dip->partition_cfg[i].hash_table,
622 dip->partition_cfg[i].force_verify_block) != 0);
Reut Zysmanff6bab92016-02-09 14:06:31 +0200623
624 if((verify_temp_result) && (strcmp("mdtp",dip->partition_cfg[i].name) == 0)){
625 *verify_result = VERIFY_MDTP_FAILED;
626 }
627
628 verify_failure |= verify_temp_result;
Amit Blay8a510302015-08-17 09:20:01 +0300629 }
630 }
631
632 ext_partition_verify_failure = verify_ext_partition(ext_partition);
633
634 if (verify_failure || ext_partition_verify_failure)
635 {
636 dprintf(CRITICAL, "mdtp: verify_all_partitions: Failed partition verification\n");
637 return;
Amit Blay6281ebc2015-01-11 14:44:08 +0200638 }
639 }
Shay Nachmanibc10dfe2015-02-10 14:45:55 +0200640 is_mdtp_activated = 1;
Amit Blay6281ebc2015-01-11 14:44:08 +0200641 }
642
643 *verify_result = VERIFY_OK;
Amit Blay8e2731c2015-04-28 21:54:55 +0300644 return;
Amit Blay6281ebc2015-01-11 14:44:08 +0200645}
646
647/* Verify the DIP and all protected partitions */
Amit Blay4aa292f2015-04-28 21:55:59 +0300648static void validate_DIP_and_firmware(mdtp_ext_partition_verification_t *ext_partition)
Amit Blay6281ebc2015-01-11 14:44:08 +0200649{
650 int ret;
Amit Blaydf42d2f2015-02-03 16:37:09 +0200651 DIP_t *enc_dip;
652 DIP_t *dec_dip;
Amit Blay6281ebc2015-01-11 14:44:08 +0200653 uint32_t verified = 0;
654 verify_result_t verify_result;
Amit Blaydf42d2f2015-02-03 16:37:09 +0200655 uint32_t block_size = mmc_get_device_blocksize();
Amit Blay4aa292f2015-04-28 21:55:59 +0300656 mdtp_cfg_t mdtp_cfg;
Amit Blay6281ebc2015-01-11 14:44:08 +0200657
658 enc_dip = malloc(ROUNDUP(sizeof(DIP_t), block_size));
659 if (enc_dip == NULL)
660 {
Reut Zysman18411272015-02-09 13:47:27 +0200661 dprintf(CRITICAL, "mdtp: validate_DIP_and_firmware: ERROR, cannot allocate DIP\n");
Amit Blay8e2731c2015-04-28 21:54:55 +0300662 display_error_msg(); /* This will never return */
Amit Blay6281ebc2015-01-11 14:44:08 +0200663 }
664
665 dec_dip = malloc(ROUNDUP(sizeof(DIP_t), block_size));
666 if (dec_dip == NULL)
667 {
Reut Zysman18411272015-02-09 13:47:27 +0200668 dprintf(CRITICAL, "mdtp: validate_DIP_and_firmware: ERROR, cannot allocate DIP\n");
Amit Blay6281ebc2015-01-11 14:44:08 +0200669 free(enc_dip);
Amit Blay8e2731c2015-04-28 21:54:55 +0300670 display_error_msg(); /* This will never return */
Amit Blay6281ebc2015-01-11 14:44:08 +0200671 }
672
673 /* Read the DIP holding the MDTP Firmware Lock state from the DIP partition */
674 ret = read_DIP(enc_dip);
675 if(ret < 0)
676 {
677 dprintf(CRITICAL, "mdtp: validate_DIP_and_firmware: ERROR, cannot read DIP\n");
Amit Blay8e2731c2015-04-28 21:54:55 +0300678 display_error_msg(); /* This will never return */
Amit Blay6281ebc2015-01-11 14:44:08 +0200679 }
680
681 /* Decrypt and verify the integrity of the DIP */
682 ret = mdtp_tzbsp_dec_verify_DIP(enc_dip, dec_dip, &verified);
683 if(ret < 0)
684 {
685 dprintf(CRITICAL, "mdtp: validate_DIP_and_firmware: ERROR, cannot verify DIP\n");
Amit Blay8e2731c2015-04-28 21:54:55 +0300686 display_error_msg(); /* This will never return */
Amit Blay6281ebc2015-01-11 14:44:08 +0200687 }
688
689 /* In case DIP integrity verification fails, notify the user and halt */
690 if(!verified)
691 {
692 dprintf(CRITICAL, "mdtp: validate_DIP_and_firmware: ERROR, corrupted DIP\n");
Amit Blay8e2731c2015-04-28 21:54:55 +0300693 display_error_msg(); /* This will never return */
Amit Blay6281ebc2015-01-11 14:44:08 +0200694 }
695
Amit Blay4aa292f2015-04-28 21:55:59 +0300696 /* Verify the integrity of the partitions which are protected, according to the content of the DIP */
697 verify_all_partitions(dec_dip, ext_partition, &verify_result);
698
699 mdtp_cfg = dec_dip->mdtp_cfg;
Amit Blay8e2731c2015-04-28 21:54:55 +0300700
701 /* Clear decrypted DIP since we don't need it anymore */
702 memset(dec_dip, 0, sizeof(DIP_t));
Amit Blay6281ebc2015-01-11 14:44:08 +0200703
Amit Blay4aa292f2015-04-28 21:55:59 +0300704
Amit Blay6281ebc2015-01-11 14:44:08 +0200705 if (verify_result == VERIFY_OK)
706 {
Reut Zysman18411272015-02-09 13:47:27 +0200707 dprintf(SPEW, "mdtp: validate_DIP_and_firmware: Verify OK\n");
Amit Blay6281ebc2015-01-11 14:44:08 +0200708 }
Amit Blay8e2731c2015-04-28 21:54:55 +0300709 else if (verify_result == VERIFY_SKIPPED)
710 {
711 dprintf(SPEW, "mdtp: validate_DIP_and_firmware: Verify skipped\n");
Reut Zysmanff6bab92016-02-09 14:06:31 +0200712 }
713 else if(verify_result == VERIFY_MDTP_FAILED)
714 {
715 dprintf(CRITICAL, "mdtp: validate_DIP_and_firmware: ERROR, corrupted mdtp image\n");
716 display_mdtp_fail_recovery_ui();
717 }
718 else /* VERIFY_FAILED */
Amit Blay6281ebc2015-01-11 14:44:08 +0200719 {
720 dprintf(CRITICAL, "mdtp: validate_DIP_and_firmware: ERROR, corrupted firmware\n");
Amit Blay4aa292f2015-04-28 21:55:59 +0300721 display_recovery_ui(&mdtp_cfg);
Amit Blay6281ebc2015-01-11 14:44:08 +0200722 }
723
Amit Blay4aa292f2015-04-28 21:55:59 +0300724 memset(&mdtp_cfg, 0, sizeof(mdtp_cfg));
725
Amit Blay6281ebc2015-01-11 14:44:08 +0200726 free(enc_dip);
727 free(dec_dip);
728
729 return;
730}
731
Reut Zysmanff6bab92016-02-09 14:06:31 +0200732
Amit Blay6281ebc2015-01-11 14:44:08 +0200733/********************************************************************************/
734
Amit Blay4aa292f2015-04-28 21:55:59 +0300735/** Entry point of the MDTP Firmware Lock.
736 * If needed, verify the DIP and all protected partitions.
737 * Allow passing information about partition verified using an external method
738 * (either boot or recovery). For boot and recovery, either use aboot's
739 * verification result, or use boot_verifier APIs to verify internally.
740 **/
741void mdtp_fwlock_verify_lock(mdtp_ext_partition_verification_t *ext_partition)
Amit Blay6281ebc2015-01-11 14:44:08 +0200742{
Amit Blaydf42d2f2015-02-03 16:37:09 +0200743 int ret;
744 bool enabled;
Amit Blay6281ebc2015-01-11 14:44:08 +0200745
Reut Zysmanff6bab92016-02-09 14:06:31 +0200746 if(mdtp_fs_init() != 0){
747 dprintf(CRITICAL, "mdtp: mdtp_img: ERROR, image file could not be loaded\n");
748 display_error_msg_mdtp(); /* This will never return */
749 }
Shay Nachmanibc10dfe2015-02-10 14:45:55 +0200750 /* sets the default value of this global to be MDTP not activated */
751 is_mdtp_activated = 0;
752
Amit Blay4aa292f2015-04-28 21:55:59 +0300753 do {
754 if (ext_partition == NULL)
755 {
756 dprintf(CRITICAL, "mdtp: mdtp_fwlock_verify_lock: ERROR, external partition is NULL\n");
757 display_error_msg(); /* This will never return */
758 break;
759 }
Amit Blay6281ebc2015-01-11 14:44:08 +0200760
Amit Blay4aa292f2015-04-28 21:55:59 +0300761 ret = mdtp_fuse_get_enabled(&enabled);
762 if(ret)
763 {
764 dprintf(CRITICAL, "mdtp: mdtp_fwlock_verify_lock: ERROR, cannot get enabled fuse\n");
765 display_error_msg(); /* This will never return */
766 }
767
768 /* Continue with Firmware Lock verification only if enabled by eFuse */
769 if (enabled)
770 {
771 /* This function will handle firmware verification failure via UI */
772 validate_DIP_and_firmware(ext_partition);
773 }
774 } while (0);
775
776 /* Disallow CIPHER_DIP SCM call from this point, unless we are in recovery */
777 /* The recovery image will disallow CIPHER_DIP SCM call by itself. */
Amit Blay8a510302015-08-17 09:20:01 +0300778 if (ext_partition->partition == MDTP_PARTITION_BOOT)
Amit Blay6281ebc2015-01-11 14:44:08 +0200779 {
Amit Blay4aa292f2015-04-28 21:55:59 +0300780 mdtp_tzbsp_disallow_cipher_DIP();
Amit Blay6281ebc2015-01-11 14:44:08 +0200781 }
Amit Blay6281ebc2015-01-11 14:44:08 +0200782}
Shay Nachmanibc10dfe2015-02-10 14:45:55 +0200783/********************************************************************************/
784
785/** Indicates whether the MDTP is currently in ACTIVATED state **/
786int mdtp_activated(bool * activated){
787 if(is_mdtp_activated < 0){
788 /* mdtp_fwlock_verify_lock was not called before, the value is not valid */
789 return is_mdtp_activated;
790 }
791
792 *activated = is_mdtp_activated;
793 return 0;
794}
Amit Blay6281ebc2015-01-11 14:44:08 +0200795
796/********************************************************************************/
797
Amit Blay6281ebc2015-01-11 14:44:08 +0200798/* Decrypt a given DIP and verify its integrity */
Amit Blaydf42d2f2015-02-03 16:37:09 +0200799static int mdtp_tzbsp_dec_verify_DIP(DIP_t *enc_dip, DIP_t *dec_dip, uint32_t *verified)
Amit Blay6281ebc2015-01-11 14:44:08 +0200800{
Amit Blay6281ebc2015-01-11 14:44:08 +0200801 unsigned char hash[HASH_LEN];
802 SHA256_CTX sha256_ctx;
803 int ret;
804
805 ASSERT(enc_dip != NULL);
806 ASSERT(dec_dip != NULL);
807 ASSERT(verified != NULL);
808
Amit Blay4418fb42015-05-05 08:45:13 +0300809 arch_clean_invalidate_cache_range((addr_t)enc_dip, sizeof(DIP_t));
810 arch_invalidate_cache_range((addr_t)dec_dip, sizeof(DIP_t));
811
Amit Blay6281ebc2015-01-11 14:44:08 +0200812 ret = mdtp_cipher_dip_cmd((uint8_t*)enc_dip, sizeof(DIP_t),
Reut Zysman3f3eccd2016-04-20 22:05:36 +0300813 (uint8_t*)dec_dip, sizeof(DIP_t),
814 DIP_DECRYPT);
Amit Blay6281ebc2015-01-11 14:44:08 +0200815 if (ret)
816 {
817 dprintf(CRITICAL, "mdtp: mdtp_tzbsp_dec_verify_DIP: ERROR, cannot cipher DIP\n");
818 *verified = 0;
Amit Blay8e2731c2015-04-28 21:54:55 +0300819 memset(dec_dip, 0, sizeof(DIP_t));
Amit Blay6281ebc2015-01-11 14:44:08 +0200820 return -1;
821 }
822
Amit Blay4418fb42015-05-05 08:45:13 +0300823 arch_invalidate_cache_range((addr_t)dec_dip, sizeof(DIP_t));
824
Amit Blay6281ebc2015-01-11 14:44:08 +0200825 SHA256_Init(&sha256_ctx);
826 SHA256_Update(&sha256_ctx, dec_dip, sizeof(DIP_t) - HASH_LEN);
827 SHA256_Final(hash, &sha256_ctx);
828
Amit Blay8e2731c2015-04-28 21:54:55 +0300829 if (memcmp(hash, dec_dip->hash, HASH_LEN))
Amit Blay6281ebc2015-01-11 14:44:08 +0200830 {
831 *verified = 0;
Amit Blay8e2731c2015-04-28 21:54:55 +0300832 memset(dec_dip, 0, sizeof(DIP_t));
Amit Blay6281ebc2015-01-11 14:44:08 +0200833 }
834 else
835 {
836 *verified = 1;
837 }
838
839 return 0;
840}
841
Amit Blay4aa292f2015-04-28 21:55:59 +0300842/* Encrypt a given DIP and calculate its integrity information */
Amit Blaydf42d2f2015-02-03 16:37:09 +0200843static int mdtp_tzbsp_enc_hash_DIP(DIP_t *dec_dip, DIP_t *enc_dip)
Amit Blay6281ebc2015-01-11 14:44:08 +0200844{
Amit Blay6281ebc2015-01-11 14:44:08 +0200845 SHA256_CTX sha256_ctx;
846 int ret;
847
848 ASSERT(dec_dip != NULL);
849 ASSERT(enc_dip != NULL);
850
Amit Blay6281ebc2015-01-11 14:44:08 +0200851 SHA256_Init(&sha256_ctx);
852 SHA256_Update(&sha256_ctx, dec_dip, sizeof(DIP_t) - HASH_LEN);
Amit Blay8e2731c2015-04-28 21:54:55 +0300853 SHA256_Final(dec_dip->hash, &sha256_ctx);
Amit Blay6281ebc2015-01-11 14:44:08 +0200854
Amit Blay4418fb42015-05-05 08:45:13 +0300855 arch_clean_invalidate_cache_range((addr_t)dec_dip, sizeof(DIP_t));
856 arch_invalidate_cache_range((addr_t)enc_dip, sizeof(DIP_t));
857
Amit Blay6281ebc2015-01-11 14:44:08 +0200858 ret = mdtp_cipher_dip_cmd((uint8_t*)dec_dip, sizeof(DIP_t),
Reut Zysman3f3eccd2016-04-20 22:05:36 +0300859 (uint8_t*)enc_dip, sizeof(DIP_t),
860 DIP_ENCRYPT);
Amit Blay6281ebc2015-01-11 14:44:08 +0200861 if (ret)
862 {
863 dprintf(CRITICAL, "mdtp: mdtp_tzbsp_enc_hash_DIP: ERROR, cannot cipher DIP\n");
864 return -1;
865 }
866
Amit Blay4418fb42015-05-05 08:45:13 +0300867 arch_invalidate_cache_range((addr_t)enc_dip, sizeof(DIP_t));
868
Amit Blay6281ebc2015-01-11 14:44:08 +0200869 return 0;
870}
Amit Blay4aa292f2015-04-28 21:55:59 +0300871
872/* Disallow the CIPHER_DIP SCM call */
873static void mdtp_tzbsp_disallow_cipher_DIP(void)
874{
875 DIP_t *dip;
876 int i;
877
878 dip = malloc(sizeof(DIP_t));
879 if (dip == NULL)
880 {
881 dprintf(CRITICAL, "mdtp: mdtp_tzbsp_disallow_cipher_DIP: ERROR, cannot allocate DIP\n");
Amir Kotzer7c768c02016-04-13 09:08:05 +0300882 /* Could not allocate DIP - stop device from booting */
883 display_error_msg(); /* This will never return */
Amit Blay4aa292f2015-04-28 21:55:59 +0300884 }
885
886 /* Disallow the CIPHER_DIP SCM by calling it MAX_CIPHER_DIP_SCM_CALLS times */
887 for (i=0; i<MAX_CIPHER_DIP_SCM_CALLS; i++)
888 {
Reut Zysman3f3eccd2016-04-20 22:05:36 +0300889 mdtp_tzbsp_enc_hash_DIP(dip, dip);
Amit Blay4aa292f2015-04-28 21:55:59 +0300890 }
891
892 free(dip);
893}
Amir Kotzerbb8be142016-02-23 09:38:25 +0200894
895/********************************************************************************/
896
897/** UT functions **/
898
899/** Hashing fuctions UT **/
900int mdtp_verify_hash_ut(){
901 unsigned char digest[HASH_LEN]={0};
902 unsigned int hash_expected_result = 0xD42B0A29;
903 char *buf = "MTDP LK UT hashing functions sanity check";
904 int size = 0;
905 DIP_hash_table_entry_t partition_hash_table;
906 uint8_t partition_force_verify_block = 0;
907
908 char ptr = buf[0];
909 while(ptr){
910 ptr = buf[++size];
911 }
912 //Bad partition name - single mode
913 if(verify_partition_single_hash("BAD_PARTITION", 1, &partition_hash_table) != -1){
914 dprintf(INFO, "verify_hash_ut: [FAIL (1)].\n");
915 return -1;
916 }
917
918 //Bad partition name - block mode
919 if(verify_partition_block_hash("BAD_PARTITION", 1, 1, &partition_hash_table, &partition_force_verify_block) != -1){
920 dprintf(INFO, "verify_hash_ut: [FAIL (2)].\n");
921 return -1;
922 }
923
924 //Hashing sanity check
925 hash_find((unsigned char*)buf, size, digest, CRYPTO_AUTH_ALG_SHA256);
926 unsigned int *hash_res = (unsigned int *)digest;
927 if (*hash_res != hash_expected_result){
928 dprintf(INFO, "verify_hash_ut: [FAIL (3)].\n");
929 return -1;
930 }
931 dprintf(INFO, "verify_hash_ut: [PASS].\n");
932 return 0;
933}
934
935/** Validate partitions params UT **/
936int mdtp_validate_partition_params_ut(){
937 int partition_size = 10;
938 //Bad size
939 if(validate_partition_params(BAD_PARAM_SIZE, MDTP_FWLOCK_MODE_SINGLE, 1) != -1){
940 dprintf(INFO, "validate_partition_params_ut: [FAIL (1)].\n");
941 return -1;
942 }
943
944 //Bad size
945 if(validate_partition_params((uint64_t)MDTP_FWLOCK_BLOCK_SIZE * (uint64_t)MAX_BLOCKS + 1,
Reut Zysman3f3eccd2016-04-20 22:05:36 +0300946 MDTP_FWLOCK_MODE_SINGLE, 1) != -1){
Amir Kotzerbb8be142016-02-23 09:38:25 +0200947 dprintf(INFO, "validate_partition_params_ut: [FAIL (2)].\n");
948 return -1;
949 }
950
951 //Bad verification ratio
952 if(validate_partition_params(partition_size, MDTP_FWLOCK_MODE_SIZE, BAD_PARAM_VERIF_RATIO) != -1){
953 dprintf(INFO, "validate_partition_params_ut: [FAIL (3)].\n");
954 return -1;
955 }
956 dprintf(INFO, "MDTP LK UT: validate_partition_params_ut [ PASS ]\n");
957 return 0;
958}
959
960/** Verify partition UT **/
961int mdtp_verify_partition_ut(){
962 uint8_t partition_force_verify_block = 0;
963 DIP_hash_table_entry_t partition_hash_table;
964 int verify_num_blocks = 10,partition_size = 1;
965
966 //Unkown hashing mode
967 if(verify_partition("system", partition_size, BAD_HASH_MODE, verify_num_blocks,
Reut Zysman3f3eccd2016-04-20 22:05:36 +0300968 &partition_hash_table, &partition_force_verify_block) != -1){
Amir Kotzerbb8be142016-02-23 09:38:25 +0200969 dprintf(INFO, "verify_partition_ut: Failed Test 1.\n");
970 dprintf(INFO, "MDTP LK UT: verify_partition_ut [ FAIL ]\n");
971 return -1;
972 }
973 dprintf(INFO, "MDTP LK UT: verify_partition_ut [ PASS ]\n");
974 return 0;
975}
976