Skip to content

Commit 4978b03

Browse files
committed
qdl: add support for vip table of digests generation
Add support for Digests Table generation for Validated Image Programming (VIP), which is activated when Secure Boot is enabled on the target. VIP controls which packets are allowed to be issued to the target. Controlling the packets that can be sent to the target is done through hashing. The target applies a hashing function to all received data, comparing the resulting hash digest against an existing digest table in memory. If the calculated hash digest matches the next entry in the table, the packet (data or command) is accepted; otherwise, the packet is rejected, and the target halts. This change introduces logic for VIP table generation. In the current VIP design the first signed hash table can be a maximum of 8 KB. Considering that it must be in MBN format, and in addition to the raw hash table, it also includes an MBN header, a signature, and certificates, the number of hash digests it can contain is limited to 54 hashes (a 40-byte MBN header + a 1696-byte hash table + a 256-byte signature + 6144 bytes of certificates). All hashes left are stored in the additional ChainedTableOfDigests.bin file. To generate table of digests run QDL with --createdigests param. As a result 3 files are generated: - DIGEST_TABLE.bin - contains the SHA256 table of digests for all firehose packets to be sent to the target. It is an intermediary table and is used only for the subsequent generation of "DigestsToSign.bin" and "ChainedTableOfDigests.bin" files. It is not used by QDL for VIP programming. - DigestsToSign.bin - first 53 digests + digest of ChainedTableOfDigests.bin. This file has to be converted to MBN format and then signed with sectools: $ sectools mbn-tool generate --data DigestsToSign.bin --mbn-version 6 --outfile DigestsToSign.bin.mbn Please check the security profile for your SoC to determine which version of the MBN format should be used. - ChainedTableOfDigests.bin - contains left digests For example, for N packets supposed to be sent to the target, these files will be generated (all digests are 32 bytes in size): DIGEST_TABLE.bin ___________________ | Digest 0 | | Digest 1 | | etc. | | | | Digest N | |___________________| DigestsTableToSign.bin ChainedTableOfDigests.bin ___________________ ___________________ | Digest 0 | | Digest 53 | | Digest 1 | | Digest 54 | | etc. | | etc. | | Digest 52 | | Digest N | | Next table digest----> progagates the --------> |___________________| |___________________| digital signature to the chained DigestsTable When QDL is executed with --debug parameter, it will also report Firehose packet SHA-256 hashes, for example: FIREHOSE WRITE: <?xml version="1.0"?> <data><patch SECTOR_SIZE_IN_BYTES="4096" byte_offset="72" filename="DISK" physical_partition_number="5" size_in_bytes="8" start_sector="NUM_DISK_SECTORS-1" value="NUM_DISK_SECTORS-5."/></data> FIREHOSE PACKET SHA256: a27b1459042ea36f654c5eed795730bf73ce37ce5e92e204fe06833e5e5e1749 Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
1 parent 3ec26b3 commit 4978b03

File tree

9 files changed

+413
-12
lines changed

9 files changed

+413
-12
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ CFLAGS += -O2 -Wall -g `pkg-config --cflags libxml-2.0 libusb-1.0`
66
LDFLAGS += `pkg-config --libs libxml-2.0 libusb-1.0`
77
prefix := /usr/local
88

9-
QDL_SRCS := firehose.c io.c qdl.c sahara.c util.c patch.c program.c read.c sim.c ufs.c usb.c ux.c oscompat.c
9+
QDL_SRCS := firehose.c io.c qdl.c sahara.c util.c patch.c program.c read.c sha2.c sim.c ufs.c usb.c ux.c oscompat.c vip.c
1010
QDL_OBJS := $(QDL_SRCS:.c=.o)
1111

1212
RAMDUMP_SRCS := ramdump.c sahara.c io.c sim.c usb.c util.c ux.c oscompat.c

firehose.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,9 +183,11 @@ static int firehose_write(struct qdl_device *qdl, xmlDoc *doc)
183183

184184
xmlDocDumpMemory(doc, &s, &len);
185185

186+
vip_gen_chunk_init(qdl);
187+
186188
for (;;) {
187189
ux_debug("FIREHOSE WRITE: %s\n", s);
188-
190+
vip_gen_chunk_update(qdl, s, len);
189191
ret = qdl_write(qdl, s, len);
190192
saved_errno = errno;
191193

@@ -202,6 +204,7 @@ static int firehose_write(struct qdl_device *qdl, xmlDoc *doc)
202204
}
203205
}
204206
xmlFree(s);
207+
vip_gen_chunk_store(qdl);
205208
return ret < 0 ? -saved_errno : 0;
206209
}
207210

@@ -423,6 +426,7 @@ static int firehose_program(struct qdl_device *qdl, struct program *program, int
423426

424427
lseek(fd, (off_t) program->file_offset * program->sector_size, SEEK_SET);
425428
left = num_sectors;
429+
vip_gen_chunk_init(qdl);
426430
while (left > 0) {
427431
chunk_size = MIN(max_payload_size / program->sector_size, left);
428432

@@ -435,6 +439,7 @@ static int firehose_program(struct qdl_device *qdl, struct program *program, int
435439
if (n < max_payload_size)
436440
memset(buf + n, 0, max_payload_size - n);
437441

442+
vip_gen_chunk_update(qdl, buf, chunk_size * program->sector_size);
438443
n = qdl_write(qdl, buf, chunk_size * program->sector_size);
439444
if (n < 0) {
440445
ux_err("USB write failed for data chunk\n");
@@ -454,6 +459,8 @@ static int firehose_program(struct qdl_device *qdl, struct program *program, int
454459
ux_debug("FIREHOSE RAW BINARY WRITE: %s, %d bytes\n",
455460
program->filename, program->sector_size * num_sectors);
456461

462+
vip_gen_chunk_store(qdl);
463+
457464
t = time(NULL) - t0;
458465

459466
ret = firehose_read(qdl, 30000, firehose_generic_parser, NULL);

qdl.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ int main(int argc, char **argv)
126126
bool qdl_finalize_provisioning = false;
127127
bool allow_fusing = false;
128128
bool allow_missing = false;
129+
bool create_digests = false;
129130
long out_chunk_size = 0;
130131
struct qdl_device *qdl = NULL;
131132
enum QDL_DEVICE_TYPE qdl_dev_type = QDL_DEVICE_USB;
@@ -141,6 +142,7 @@ int main(int argc, char **argv)
141142
{"allow-missing", no_argument, 0, 'f'},
142143
{"allow-fusing", no_argument, 0, 'c'},
143144
{"dry-run", no_argument, 0, 'n'},
145+
{"createdigests", no_argument, 0, 't'},
144146
{0, 0, 0, 0}
145147
};
146148

@@ -152,6 +154,11 @@ int main(int argc, char **argv)
152154
case 'n':
153155
qdl_dev_type = QDL_DEVICE_SIM;
154156
break;
157+
case 't':
158+
create_digests = true;
159+
/* we also enforce dry-run mode */
160+
qdl_dev_type = QDL_DEVICE_SIM;
161+
break;
155162
case 'v':
156163
print_version();
157164
return 0;
@@ -197,6 +204,9 @@ int main(int argc, char **argv)
197204
if (out_chunk_size)
198205
qdl_set_out_chunk_size(qdl, out_chunk_size);
199206

207+
if (create_digests)
208+
vip_gen_init(qdl);
209+
200210
ux_init();
201211

202212
if (qdl_debug)
@@ -254,6 +264,9 @@ int main(int argc, char **argv)
254264
goto out_cleanup;
255265

256266
out_cleanup:
267+
if (create_digests)
268+
vip_gen_finalize(qdl);
269+
257270
qdl_close(qdl);
258271
free_programs();
259272
free_patches();

qdl.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
#include "read.h"
99
#include <libxml/tree.h>
1010

11+
#define container_of(ptr, typecast, member) ({ \
12+
void *_ptr = (void *)(ptr); \
13+
((typecast *)(_ptr - offsetof(typecast, member))); })
14+
1115
#define MAPPING_SZ 64
1216

1317
enum QDL_DEVICE_TYPE
@@ -43,6 +47,12 @@ void qdl_set_out_chunk_size(struct qdl_device *qdl, long size);
4347
struct qdl_device *usb_init(void);
4448
struct qdl_device *sim_init(void);
4549

50+
void vip_gen_init(struct qdl_device *qdl);
51+
void vip_gen_chunk_init(struct qdl_device *qdl);
52+
void vip_gen_chunk_update(struct qdl_device *qdl, const void *buf, size_t len);
53+
void vip_gen_chunk_store(struct qdl_device *qdl);
54+
void vip_gen_finalize(struct qdl_device *qdl);
55+
4656
int firehose_run(struct qdl_device *qdl, const char *incdir, const char *storage, bool allow_missing);
4757
int sahara_run(struct qdl_device *qdl, char *img_arr[], bool single_image,
4858
const char *ramdump_path, const char *ramdump_filter);

sim.c

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,7 @@
3030
#include <stdlib.h>
3131
#include <string.h>
3232

33-
#include "qdl.h"
34-
35-
struct qdl_device_sim
36-
{
37-
struct qdl_device base;
38-
};
33+
#include "sim.h"
3934

4035
static int sim_open(struct qdl_device *qdl, const char *serial)
4136
{

sim.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright (c) 2025, Qualcomm Innovation Center, Inc. All rights reserved.
3+
*
4+
* Redistribution and use in source and binary forms, with or without
5+
* modification, are permitted provided that the following conditions are met:
6+
*
7+
* 1. Redistributions of source code must retain the above copyright notice,
8+
* this list of conditions and the following disclaimer.
9+
*
10+
* 2. Redistributions in binary form must reproduce the above copyright notice,
11+
* this list of conditions and the following disclaimer in the documentation
12+
* and/or other materials provided with the distribution.
13+
*
14+
* 3. Neither the name of the copyright holder nor the names of its contributors
15+
* may be used to endorse or promote products derived from this software without
16+
* specific prior written permission.
17+
*
18+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28+
* POSSIBILITY OF SUCH DAMAGE.
29+
*/
30+
#ifndef __SIM_H__
31+
#define __SIM_H__
32+
33+
#include "qdl.h"
34+
#include "vip.h"
35+
36+
struct qdl_device_sim
37+
{
38+
struct qdl_device base;
39+
struct vip_table_generator vip_gen;
40+
bool create_digests;
41+
};
42+
43+
#endif /* __SIM_H__ */

usb.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,6 @@
99

1010
#include "qdl.h"
1111

12-
#define container_of(ptr, typecast, member) ({ \
13-
void *_ptr = (void *)(ptr); \
14-
((typecast *)(_ptr - offsetof(typecast, member))); })
15-
1612
#define DEFAULT_OUT_CHUNK_SIZE (1024 * 1024)
1713

1814
struct qdl_device_usb

0 commit comments

Comments
 (0)