Skip to content

Commit

Permalink
Pull request #236: Add code signature verification to HSS Payload Gen…
Browse files Browse the repository at this point in the history
…erator (SAR 138991)

Merge in FPGA_PFSOC_ES/hart-software-services from next-feature-payload-gen-code-sign-verify to next

* commit 'aec7250e2e1337bb05676e68f9a8f664f3ddb6e4':
  feat(hss-payload-gen): Update README
  feat(hss-payload-gen): Add verify to code signing
  • Loading branch information
Ivan Griffin authored and vfalanis committed Oct 25, 2024
2 parents d4f2641 + aec7250 commit 00e919e
Show file tree
Hide file tree
Showing 21 changed files with 383 additions and 51 deletions.
1 change: 1 addition & 0 deletions tools/hss-payload-generator/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ SRCS=\
generate_payload.c \
dump_payload.c \
debug_printf.c \
verify_payload.c \

OBJS := $(patsubst %.c,$(build_dir)/%.o,$(SRCS))

Expand Down
11 changes: 9 additions & 2 deletions tools/hss-payload-generator/README.md
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
% HSS Payload Generator
% 2022-09-02
% 2024-10-14

# Introduction

Expand All @@ -21,10 +21,17 @@ To print diagnostics about a pre-existing image, use `-d`:

To enable secure boot authentication (via image signing), use `-p` to specify the location of an X.509 Private Key for the Elliptic Curve P-384 (SECP384r1):

$ ./hss-payload-generator -c test/config.yaml payload.bin -p /path/to/private.pem
$ ./hss-payload-generator -c test/config.yaml -p /path/to/private.pem payload.bin

See the documentation on secure boot authentication for more details.

To verify secure boot code signing, use the `-u` option to specify the location of a DER format Public Key for the Elliptic Curve P-384 (SECP384r1). This option is compatible with either `-p` (during generation) or `-d` during image inspection - for example:

$ ./hss-payload-generator -p x509-ec-secp384r1-private.pem -c config.yaml -u x509-ec-secp384r1-public.der payload.bin
$ ./hss-payload-generator -u x509-ec-secp384r1-public.der -d payload.bin

NOTE: specifically when on Microsoft Windows, ensure that the `payload.bin` argument is at the end of the command line when creating a payload image. We recommend also making the `payload.bin` argument the last argument on Linux.

## Config File example

First, we can optionally set a name for our image, otherwise one will be created dynamically:
Expand Down
2 changes: 1 addition & 1 deletion tools/hss-payload-generator/blob_handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
*
* MPFS HSS Embedded Software - tools/hss-payload-generator
*
* Copyright 2020-2022 Microchip FPGA Embedded Systems Solutions.
* Copyright 2020-2024 Microchip FPGA Embedded Systems Solutions.
*
* SPDX-License-Identifier: MIT
*
Expand Down
2 changes: 1 addition & 1 deletion tools/hss-payload-generator/blob_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*
* MPFS HSS Embedded Software - tools/hss-payload-generator
*
* Copyright 2020-2022 Microchip FPGA Embedded Systems Solutions.
* Copyright 2020-2024 Microchip FPGA Embedded Systems Solutions.
*
* SPDX-License-Identifier: MIT
*
Expand Down
2 changes: 1 addition & 1 deletion tools/hss-payload-generator/crc32.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
*
* MPFS HSS Embedded Software - tools/hss-payload-generator
*
* Copyright 2020-2022 Microchip FPGA Embedded Systems Solutions.
* Copyright 2020-2024 Microchip FPGA Embedded Systems Solutions.
*
* SPDX-License-Identifier: MIT
*
Expand Down
2 changes: 1 addition & 1 deletion tools/hss-payload-generator/crc32.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*
* MPFS HSS Embedded Software - tools/hss-payload-generator
*
* Copyright 2020-2022 Microchip FPGA Embedded Systems Solutions.
* Copyright 2020-2024 Microchip FPGA Embedded Systems Solutions.
*
* SPDX-License-Identifier: MIT
*
Expand Down
2 changes: 1 addition & 1 deletion tools/hss-payload-generator/debug_printf.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
*
* MPFS HSS Embedded Software - tools/hss-payload-generator
*
* Copyright 2020-2022 Microchip FPGA Embedded Systems Solutions.
* Copyright 2020-2024 Microchip FPGA Embedded Systems Solutions.
*
* SPDX-License-Identifier: MIT
*
Expand Down
2 changes: 1 addition & 1 deletion tools/hss-payload-generator/debug_printf.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*
* MPFS HSS Embedded Software - tools/hss-payload-generator
*
* Copyright 2020-2022 Microchip FPGA Embedded Systems Solutions.
* Copyright 2020-2024 Microchip FPGA Embedded Systems Solutions.
*
* SPDX-License-Identifier: MIT
*
Expand Down
16 changes: 13 additions & 3 deletions tools/hss-payload-generator/dump_payload.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
*
* MPFS HSS Embedded Software - tools/hss-payload-generator
*
* Copyright 2020-2022 Microchip FPGA Embedded Systems Solutions.
* Copyright 2020-2024 Microchip FPGA Embedded Systems Solutions.
*
* SPDX-License-Identifier: MIT
*
Expand Down Expand Up @@ -43,6 +43,7 @@
#include "debug_printf.h"
#include "dump_payload.h"
#include "crc32.h"
#include "verify_payload.h"

#define PRV_U (0u)
#define PRV_S (1u)
Expand Down Expand Up @@ -85,7 +86,7 @@ static char const * privModeToString(uint8_t privMode)
return result;
}

void dump_payload(const char *filename_input)
void dump_payload(const char *filename_input, const char *public_key_filename)
{
printf("opening >>%s<<\n", filename_input);
int fdIn = open(filename_input, O_RDONLY);
Expand All @@ -94,8 +95,12 @@ void dump_payload(const char *filename_input)
size_t fileSize = getFileSize(filename_input);

struct HSS_BootImage *pBootImage;
void *raw_image;

pBootImage = mmap(NULL, fileSize, PROT_READ, MAP_PRIVATE, fdIn, 0);
raw_image = mmap(NULL, fileSize, PROT_READ, MAP_PRIVATE, fdIn, 0);
debug_printf(6, "Mapped %d (%x) bytes at %p (to %p)\n", fileSize, fileSize, raw_image, ((uint8_t*)raw_image) + fileSize);

pBootImage = (struct HSS_BootImage *)raw_image;
assert(pBootImage);
if (pBootImage == MAP_FAILED) {
perror("mmap()");
Expand Down Expand Up @@ -236,6 +241,11 @@ void dump_payload(const char *filename_input)

// skipping binary file array

if (public_key_filename) {
bool result = HSS_Boot_Secure_CheckCodeSigning(raw_image, public_key_filename);
printf("Public Key Specified so verifying signature... %s\n\n", result ? "passed" : "failed");
}

munmap(pBootImage, fileSize);
close(fdIn);
}
4 changes: 2 additions & 2 deletions tools/hss-payload-generator/dump_payload.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*
* MPFS HSS Embedded Software - tools/hss-payload-generator
*
* Copyright 2020-2022 Microchip FPGA Embedded Systems Solutions.
* Copyright 2020-2024 Microchip FPGA Embedded Systems Solutions.
*
* SPDX-License-Identifier: MIT
*
Expand All @@ -32,6 +32,6 @@
#include <stddef.h>
#include <stdint.h>

void dump_payload(char const * filename);
void dump_payload(char const * filename, char const * public_key_filename);

#endif
2 changes: 1 addition & 1 deletion tools/hss-payload-generator/elf_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
*
* MPFS HSS Embedded Software - tools/hss-payload-generator
*
* Copyright 2020-2022 Microchip FPGA Embedded Systems Solutions.
* Copyright 2020-2024 Microchip FPGA Embedded Systems Solutions.
*
* SPDX-License-Identifier: MIT
*
Expand Down
2 changes: 1 addition & 1 deletion tools/hss-payload-generator/elf_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*
* MPFS HSS Embedded Software - tools/hss-payload-generator
*
* Copyright 2020-2022 Microchip FPGA Embedded Systems Solutions.
* Copyright 2020-2024 Microchip FPGA Embedded Systems Solutions.
*
* SPDX-License-Identifier: MIT
*
Expand Down
2 changes: 1 addition & 1 deletion tools/hss-payload-generator/elf_strings.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
*
* MPFS HSS Embedded Software - tools/hss-payload-generator
*
* Copyright 2020-2022 Microchip FPGA Embedded Systems Solutions.
* Copyright 2020-2024 Microchip FPGA Embedded Systems Solutions.
*
* SPDX-License-Identifier: MIT
*
Expand Down
2 changes: 1 addition & 1 deletion tools/hss-payload-generator/elf_strings.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*
* MPFS HSS Embedded Software - tools/hss-payload-generator
*
* Copyright 2020-2022 Microchip FPGA Embedded Systems Solutions.
* Copyright 2020-2024 Microchip FPGA Embedded Systems Solutions.
*
* SPDX-License-Identifier: MIT
*
Expand Down
85 changes: 62 additions & 23 deletions tools/hss-payload-generator/generate_payload.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
*
* MPFS HSS Embedded Software - tools/hss-payload-generator
*
* Copyright 2020-2022 Microchip FPGA Embedded Systems Solutions.
* Copyright 2020-2024 Microchip FPGA Embedded Systems Solutions.
*
* SPDX-License-Identifier: MIT
*
Expand Down Expand Up @@ -35,6 +35,7 @@
#include <libgen.h>
#include "crc32.h"
#include "debug_printf.h"
#include "verify_payload.h"

#include <openssl/ec.h>
#include <openssl/ecdsa.h>
Expand Down Expand Up @@ -118,7 +119,8 @@ static void generate_header(FILE *pFileOut, struct HSS_BootImage *pBootImage) __
static void generate_chunks(FILE *pFileOut) __attribute__((nonnull));
static void generate_ziChunks(FILE *pFileOut) __attribute__((nonnull));
static void generate_blobs(FILE *pFileOut) __attribute__((nonnull));
static void sign_payload(FILE *pFileOut, char const * const private_key_filename) __attribute__((nonnull(1)));
static void sign_payload(FILE *pFileOut, char const * const private_key_filename,
char const * const public_key_filename) __attribute__((nonnull(1)));

extern struct HSS_BootImage bootImage;

Expand Down Expand Up @@ -210,7 +212,7 @@ static void generate_chunks(FILE *pFileOut)
cumulativeBlobSize += chunkTable[i].chunk.size
+ calculate_padding(chunkTable[i].chunk.size, PAD_SIZE);

off_t posn = ftello(pFileOut);
off_t posn = ftello(pFileOut);
debug_printf(4, "\t- Processing chunk %lu (%lu bytes) at file position %lu "
"(blob is expected at %lu)\n",
i, chunkTable[i].chunk.size, posn, chunkTable[i].chunk.loadAddr);
Expand Down Expand Up @@ -259,7 +261,7 @@ static void generate_ziChunks(FILE *pFileOut)
+ calculate_padding(sizeof(struct HSS_BootChunkDesc) * (numChunks+1), PAD_SIZE));

for (size_t i = 0u; i < numZIChunks; i++) {
off_t posn = ftello(pFileOut);
off_t posn = ftello(pFileOut);
debug_printf(4, "\t- Processing ziChunk %lu (%lu bytes) at file position %lu\n",
i, ziChunkTable[i].ziChunk.size, posn);

Expand Down Expand Up @@ -302,7 +304,7 @@ static void generate_blobs(FILE *pFileOut)
+ calculate_padding(sizeof(struct HSS_BootZIChunkDesc) * (numZIChunks +1), PAD_SIZE));

for (size_t i = 0u; i < numChunks; i++) {
off_t posn = ftello(pFileOut);
off_t posn = ftello(pFileOut);
debug_printf(4, "\t- Processing blob %lu (%lu bytes) at file position %lu\n",
i, chunkTable[i].chunk.size, posn);
debug_printf(4, "\t\tCRC32: %x\n",
Expand All @@ -323,7 +325,8 @@ static void generate_blobs(FILE *pFileOut)
assert(pFileOut);
}

static void sign_payload(FILE *pFileOut, char const * const private_key_filename)
static void sign_payload(FILE *pFileOut, char const * const private_key_filename,
char const * const public_key_filename)
{
if (private_key_filename) {
//
Expand Down Expand Up @@ -352,22 +355,29 @@ static void sign_payload(FILE *pFileOut, char const * const private_key_filename

EVP_PKEY *pPrivKey = PEM_read_PrivateKey(privKeyFileIn, NULL, NULL, NULL);
assert(pPrivKey != NULL);
fclose(privKeyFileIn);
fclose(privKeyFileIn);

// create the signature by using SHA384 digest and signing with our SECP384r1 private key
//
EVP_MD_CTX *pCtx = EVP_MD_CTX_new();
assert(pCtx != NULL);

assert(EVP_DigestInit_ex(pCtx, EVP_sha384(), NULL) == 1);

uint8_t digest[EVP_MAX_MD_SIZE];
unsigned int digest_len = 0;
assert(EVP_DigestUpdate(pCtx, pEntirePayloadBuffer, bootImage.bootImageLength) == 1);
assert(EVP_DigestFinal_ex(pCtx, digest, &digest_len) == 1);

assert(EVP_DigestSignInit(pCtx, NULL, EVP_sha384(), NULL, pPrivKey) == 1);

size_t sigLen = 0u;
assert(EVP_DigestSign(pCtx, NULL, &sigLen, pEntirePayloadBuffer, bootImage.bootImageLength) == 1);

unsigned char *pSignatureBuffer = OPENSSL_malloc(sigLen);
assert(pSignatureBuffer);
assert(EVP_DigestSign(pCtx, pSignatureBuffer, &sigLen, pEntirePayloadBuffer, bootImage.bootImageLength) == 1);

free(pEntirePayloadBuffer);

// copy the signature to the boot image header...
// OpenSSL will output the signature is in ASN.1 format, as described in
// https://datatracker.ietf.org/doc/html/rfc5480
Expand Down Expand Up @@ -403,24 +413,26 @@ static void sign_payload(FILE *pFileOut, char const * const private_key_filename
ECDSA_SIG *pSig = d2i_ECDSA_SIG(NULL, &sig_ptr, (long)sigLen);
assert(pSig != NULL);

// the signature is in an opaque ECDSA_SIG structure, which contains two
// BIGNUMs, r and s. These are max half the curve size in bytes
// => 384 / (8*2) = 48 bytes each... but they may be less, and need to be
// zero padded, so extract separately...
const BIGNUM *pR = NULL;
const BIGNUM *pS = NULL;
ECDSA_SIG_get0(pSig, &pR, &pS);
// the signature is in an opaque ECDSA_SIG structure, which contains two
// BIGNUMs, r and s. These are max half the curve size in bytes
// => 384 / (8*2) = 48 bytes each... but they may be less, and need to be
// zero padded, so extract separately...
const BIGNUM *pR = NULL;
const BIGNUM *pS = NULL;
ECDSA_SIG_get0(pSig, &pR, &pS);

const int rBytes = BN_num_bytes(pR);
const int sBytes = BN_num_bytes(pS);
const int rBytes = BN_num_bytes(pR);
const int sBytes = BN_num_bytes(pS);

assert(rBytes == sBytes);
assert(rBytes == 48);

memset(pSignatureBuffer, 0, 96);
BN_bn2bin(pR, pSignatureBuffer + 48 - rBytes);
BN_bn2bin(pS, pSignatureBuffer + 96 - sBytes);
memset(pSignatureBuffer, 0, 96);
BN_bn2bin(pR, pSignatureBuffer + 48 - rBytes);
BN_bn2bin(pS, pSignatureBuffer + 96 - sBytes);
//

memcpy(bootImage.signature.digest, digest, 48u);
memcpy(bootImage.signature.ecdsaSig, pSignatureBuffer, 48u);
memcpy(bootImage.signature.ecdsaSig + 48u, pSignatureBuffer + 48u, 48u);

Expand All @@ -435,13 +447,40 @@ static void sign_payload(FILE *pFileOut, char const * const private_key_filename
EVP_MD_CTX_free(pCtx);
EVP_PKEY_free(pPrivKey);
OPENSSL_free(pSignatureBuffer);

// if a public key was provided, we'll cross-check the signature against it
//
if (public_key_filename) {
// refresh payload from file, as we just rewrote the header to include the signature
if (fseek(pFileOut, 0, SEEK_SET) != 0) {
perror("fseek()");
exit(EXIT_SUCCESS);
}

fileSize = fread((void *)pEntirePayloadBuffer, 1u, bootImage.bootImageLength, pFileOut);
assert(fileSize == bootImage.bootImageLength);

// now perform the cross-check
bool result = HSS_Boot_Secure_CheckCodeSigning((struct HSS_BootImage *)pEntirePayloadBuffer, public_key_filename);

printf("Signature validation using public key ... %s\n\n", result ? "passed":"failed");

}

free(pEntirePayloadBuffer);
}
}

void generate_payload(char const * const filename_output, char const * const private_key_filename)
void generate_payload(char const * const filename_output, char const * const private_key_filename, char const * const public_key_filename)
{
assert(filename_output);
printf("Output filename is >>%s<<\n", filename_output);
if (private_key_filename) {
printf("private_key_filename is >>%s<<\n", private_key_filename);
}
if (public_key_filename) {
printf("public_key_filename is >>%s<<\n", public_key_filename);
}

FILE *pFileOut = fopen(filename_output, "w+");
if (!pFileOut) {
Expand All @@ -466,7 +505,7 @@ void generate_payload(char const * const filename_output, char const * const pri

generate_header(pFileOut, &bootImage); // rewrite header for CRC...

sign_payload(pFileOut, private_key_filename);
sign_payload(pFileOut, private_key_filename, public_key_filename);

if (fclose(pFileOut) != 0) {
perror("fclose()");
Expand Down
4 changes: 2 additions & 2 deletions tools/hss-payload-generator/generate_payload.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*
* MPFS HSS Embedded Software - tools/hss-payload-generator
*
* Copyright 2020-2022 Microchip FPGA Embedded Systems Solutions.
* Copyright 2020-2024 Microchip FPGA Embedded Systems Solutions.
*
* SPDX-License-Identifier: MIT
*
Expand Down Expand Up @@ -34,7 +34,7 @@

#include "hss_types.h"

void generate_payload(char const * const filename_output, char const * const private_key_filename);
void generate_payload(char const * const filename_output, char const * const private_key_filename, char const * const public_key_filename);
void generate_init(void);

size_t generate_add_chunk(struct HSS_BootChunkDesc chunk, void *buffer) __attribute__((nonnull));
Expand Down
Loading

0 comments on commit 00e919e

Please sign in to comment.