Files
qdl/sim.c

93 lines
2.0 KiB
C
Raw Permalink Normal View History

// SPDX-License-Identifier: BSD-3-Clause
/*
* Copyright (c) 2025, Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <stdlib.h>
#include <string.h>
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<n>.bin files. To generate table of digests run QDL with --create-digests param, providing a path to store VIP tables. As a result 3 types of 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 $ sectools secure-image --sign DigestsToSign.bin.mbn --image-id=VIP Please check the security profile for your SoC to determine which version of the MBN format should be used. - ChainedTableOfDigests<n>.bin - contains left digests, split on multiple files with 255 digests + appended hash of next table. For example, for 400 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 399 | |_____________| DigestsTableToSign.bin ChainedTableOfDigests0.bin ChainedTableOfDigests1.bin ___________________ ___________________ ____________ | Digest 0 | | Digest 53 | | Digest 308 | | Digest 1 | | Digest 54 | | Digest 309 | | etc. | | etc. | | etc. | | Digest 52 | | Digest 307 | | Digest 399 | | Next table digest | | Next table digest | |____________| |___________________| |___________________| 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>
2025-05-24 11:42:00 +02:00
#include "sim.h"
struct qdl_device_sim {
struct qdl_device base;
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<n>.bin files. To generate table of digests run QDL with --create-digests param, providing a path to store VIP tables. As a result 3 types of 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 $ sectools secure-image --sign DigestsToSign.bin.mbn --image-id=VIP Please check the security profile for your SoC to determine which version of the MBN format should be used. - ChainedTableOfDigests<n>.bin - contains left digests, split on multiple files with 255 digests + appended hash of next table. For example, for 400 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 399 | |_____________| DigestsTableToSign.bin ChainedTableOfDigests0.bin ChainedTableOfDigests1.bin ___________________ ___________________ ____________ | Digest 0 | | Digest 53 | | Digest 308 | | Digest 1 | | Digest 54 | | Digest 309 | | etc. | | etc. | | etc. | | Digest 52 | | Digest 307 | | Digest 399 | | Next table digest | | Next table digest | |____________| |___________________| |___________________| 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>
2025-05-24 11:42:00 +02:00
struct vip_table_generator *vip_gen;
bool create_digests;
};
static int sim_open(struct qdl_device *qdl __unused,
const char *serial __unused)
{
ux_info("This is a dry-run execution of QDL. No actual flashing has been performed\n");
return 0;
}
static void sim_close(struct qdl_device *qdl __unused) {}
static int sim_read(struct qdl_device *qdl __unused,
void *buf __unused, size_t len,
unsigned int timeout __unused)
{
return len;
}
static int sim_write(struct qdl_device *qdl __unused, const void *buf __unused,
size_t len, unsigned int timeout __unused)
{
return len;
}
static void sim_set_out_chunk_size(struct qdl_device *qdl __unused,
long size __unused)
{}
struct qdl_device *sim_init(void)
{
struct qdl_device *qdl = malloc(sizeof(struct qdl_device_sim));
if (!qdl)
return NULL;
memset(qdl, 0, sizeof(struct qdl_device_sim));
qdl->dev_type = QDL_DEVICE_SIM;
qdl->open = sim_open;
qdl->read = sim_read;
qdl->write = sim_write;
qdl->close = sim_close;
qdl->set_out_chunk_size = sim_set_out_chunk_size;
qdl->max_payload_size = 1048576;
return qdl;
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<n>.bin files. To generate table of digests run QDL with --create-digests param, providing a path to store VIP tables. As a result 3 types of 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 $ sectools secure-image --sign DigestsToSign.bin.mbn --image-id=VIP Please check the security profile for your SoC to determine which version of the MBN format should be used. - ChainedTableOfDigests<n>.bin - contains left digests, split on multiple files with 255 digests + appended hash of next table. For example, for 400 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 399 | |_____________| DigestsTableToSign.bin ChainedTableOfDigests0.bin ChainedTableOfDigests1.bin ___________________ ___________________ ____________ | Digest 0 | | Digest 53 | | Digest 308 | | Digest 1 | | Digest 54 | | Digest 309 | | etc. | | etc. | | etc. | | Digest 52 | | Digest 307 | | Digest 399 | | Next table digest | | Next table digest | |____________| |___________________| |___________________| 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>
2025-05-24 11:42:00 +02:00
}
struct vip_table_generator *sim_get_vip_generator(struct qdl_device *qdl)
{
struct qdl_device_sim *qdl_sim;
if (qdl->dev_type != QDL_DEVICE_SIM)
return NULL;
qdl_sim = container_of(qdl, struct qdl_device_sim, base);
if (!qdl_sim->create_digests)
return NULL;
return qdl_sim->vip_gen;
}
bool sim_set_digest_generation(bool create_digests, struct qdl_device *qdl,
struct vip_table_generator *vip_gen)
{
struct qdl_device_sim *qdl_sim;
if (qdl->dev_type != QDL_DEVICE_SIM)
return false;
qdl_sim = container_of(qdl, struct qdl_device_sim, base);
qdl_sim->create_digests = create_digests;
qdl_sim->vip_gen = vip_gen;
return true;
}