1.3 Secure MCC Melody MDFU Client Library – ECDSA Signing Operation Example
A post build script automates the preparation, signing and verification of firmware images for secure application deployment. It integrates Hexmate, Python™ , OpenSSL, and avr-objcopy tools to manipulate binary and hex files, embed digital signatures, and ensure the integrity and authenticity of the application firmware before release.
Signing Process Overview:
-
Insert Blank Signature: This command takes a specific region from the input
hex, creates a temporary output and inserts zeros at the signature field, preparing
the image for digital signing.
hexmate r8000-1FFFF,%4\%3.X.production.hex -O%4\temp_original_copy.X.production.hex -FILL=w1:0x00,0x00@0xFFBC:0xFFFF-
r8000-1FFFF: Reads or extracts the address range from0x8000to0x1FFFFfrom the input hex file. This defines the region of the Flash to operate on. -
%4\%3.X.production.hex: The input hex file containing the original application image.%3and%4are script variables representing (typically) the project name and output directory, respectively. -
-O%4\temp_original_copy.X.production.hex: Specifies the output file, which will be written to%4\temp_original_copy.X.production.hex. This file is a temporary working copy with modifications applied. -
-FILL=w1:0x00,0x00@0xFFBC:0xFFFF: Fills the specified address range (0xFFBCto0xFFFF) with two consecutive 1-byte values (0x00, 0x00). w1: fill as one byte at a time (width = 1 byte).@0xFFBC:0xFFFF: applies the 0xFF fill specifically at the end of the Flash (signature location).
-
-
Fill Unimplemented Flash Locations: Uninitialized or unused Flash regions in
the specified memory range are filled with 0xFF to maintain consistency.
hexmate r0-FFFFFFFF,%4\temp_original_copy.X.production.hex -O%4\temp_original_copy.X.production.hex -FILL=w1:0xFF@0x8000:0xFFFF-
r0-FFFFFFFF: Reads or extracts the address range from0x0000to0xFFFFFFFF (end of Flash)from the input hex file. This specifies all possible addresses in the hex file for processing. -
%4\temp_original_copy.X.production.hex: The input Intel hex file to be processed.%4is a script variable representing the output or working directory.temp_original_copy.X.production.hexis a temporary working file from earlier script steps. -
-O%4\temp_original_copy.X.production.hex: Specifies the output file, overwriting the input file with the modified content. This ensures the fill operation is preserved in the same temporary hex file. -
-FILL=w1:0xFF@0x8000:0xFFFF: Fills the specified address range (0x8000to0xFFFF) with0xFFbytes.w1: indicates a fill width of one byte at a time.@0x8000:0xFFFF: applies the fill from address0x8000through0xFFFF.
-
-
Shift Data and Export Binary: The Hexmate command extracts and shifts the
active application range so it starts at 0x0000 (to align with the application’s
execution area), and the file is then converted from Intel hex format to binary;
this generates the actual image for signing.
hexmate r8000-FFBBs-8000,%4\temp_original_copy.X.production.hex -O%4\temp_original_copy.X.production.hex %2\avr-objcopy -I ihex -O binary %4\temp_original_copy.X.production.hex %4\%3.X.production.bin-
r8000-FFBB: Reads or extracts the address range from0x8000to0xFFBBfrom the input hex file, targeting the main application data area up to (but not including) the signature field. -
s-8000: Shifts the extracted address range down by0x8000bytes. This means addresses in the output will start from0x0000instead of0x8000, aligning the application image for signing. -
%4\temp_original_copy.X.production.hex: The input Intel HEX file containing the prepared application image.%4is a script variable representing the output or working directory. -
-O%4\temp_original_copy.X.production.hex: Specifies the output file, which will be written to%4\temp_original_copy.X.production.hex— overwriting with shifted content. -
%2\avr-objcopy -I ihex -O binary %4\temp_original_copy.X.production.hex %4\%3.X.production.bin: Converts the modified Intel hex file to a pure binary format for signing.%2is a script variable for the location of avr-objcopy tool-
-I ihexspecifies the input format as Intel hex -O binaryspecifies the output format as raw binary%4\temp_original_copy.X.production.hex is the input file%4\%3.X.production.binis the output file for the signed image.
-
-
Sign the Binary:This command uses OpenSSL with SHA-256 hashing and a private key to produce and save a DER-format digital signature of the application binary.openssl dgst -sha256 -sign .\sjcl_random_private_key_2.pem %4\%3.X.production.bin > %4\%3.X.production.bin.signature.deropenssl dgst: Invokes the OpenSSL command-line utility to perform cryptographic digest and signing operations.-
-sha256: Specifies the cryptographic hash algorithm (SHA-256) to compute the digest of the input file before signing. -
-sign .\sjcl_random_private_key_2.pem: Uses the private key file (sjcl_random_private_key_2.pem) to digitally sign the computed hash of the input file. -
%4\%3.X.production.bin: The input file to be signed.%3is generally the project name,%4is the target directory. -
> %4\%3.X.production.bin.signature.der: Redirects the output (the DER-encoded digital signature) to a file named%3.X.production.bin.signature.derin directory%4.
-
Verify the Signature (Optional): This command verifies the SHA-256 signature
of the specified binary file using the provided public key and signature, ensuring
the binary's authenticity and integrity. Tip: This step is optional and useful for development and debugging.
openssl dgst -sha256 -verify \"public_key.pem\" -signature %4\%3.X.production.bin.signature.der %4\%3.X.production.binopenssl dgst: Calls the OpenSSL command-line utility to perform digest and verification operations on a file.-
-sha256: Specifies the use of the SHA-256 cryptographic hash algorithm. This produces a hash of the input file for verification. -
-verify “public_key.pem“: Uses the specified public key file (public_key.pem) to verify the digital signature. The public key must match the private key used for signing. -
-signature %4\%3.X.production.bin.signature.der: The DER-encoded file containing the digital signature to be verified (%3: project name,%4: output directory) -
%4\%3.X.production.bin: The input file (application binary) whose signature is being verified.
-
Export Signature as Raw Binary: The DER-formatted signature file is
translated to a raw binary format using a Python™ script for compatibility with
embedded systems.
python \"signature_der_to_bin.py\" %4\%3.X.production.bin.signature.der %4\%3.X.production.bin.signature.bin-
python “signature_der_to_bin.py“: Invokes the Python interpreter to run thesignature_der_to_bin.pyscript, which is used to convert a DER-encoded ECDSA signature into a raw binary format. -
%4\%3.X.production.bin.signature.der: The first argument to the script. This is the path to the input file containing the DER-encoded ECDSA signature to be converted (%3: project name,%4: output directory) -
%4\%3.X.production.bin.signature.bin: The second argument to the script. This is the path to the output file where the script will write the ECDSA signature in raw binary format (concatenated r||s values). -
[curve_bytes=32](optional, not provided here): An optional (third) argument specifying the number of bytes for each component (r and s) in the output file. Defaults to 32 if not specified (suitable for NIST P-256 or secp256r1).
A sample script for
signature_der_to_bin.pyis provided below. It can be modified as required.from pyasn1.codec.der import decoder from pyasn1.type.univ import Sequence import sys def der_to_bin(der_path, bin_path, curve_bytes=32): with open(der_path, 'rb') as der_file: der_data = der_file.read() sig_seq, _ = decoder.decode(der_data, asn1Spec=Sequence()) # Get r and s integers r = int(sig_seq[0]) s = int(sig_seq[1]) # Convert to bytes, pad to proper length r_bytes = r.to_bytes(curve_bytes, byteorder="big") s_bytes = s.to_bytes(curve_bytes, byteorder="big") with open(bin_path, 'wb') as bin_file: bin_file.write(r_bytes + s_bytes) print(f"Converted {der_path} -> {bin_path}") if __name__ == "__main__": if len(sys.argv) < 3: print("Usage: python signature_der_to_bin.py signature.der signature.bin [curve_bytes=32]") sys.exit(1) der_path = sys.argv[1] bin_path = sys.argv[2] curve_bytes = int(sys.argv[3]) if len(sys.argv) > 3 else 32 der_to_bin(der_path, bin_path, curve_bytes) -
-
Convert Signature to Hex:This command converts the raw binary signature into an Intel hex file, enabling it to be embedded into the application firmware image for secure boot or verification purposes.%2\avr-objcopy -I binary -O ihex %4\%3.X.production.bin.signature.bin %4\%3.X.production.bin.signature.hex-
%2\avr-objcopy: Runs theavr-objcopyutility for converting or reformatting binary files, typically used in microcontroller development.%2is a variable pointing to the directory containing theavr-objcopyexecutable. -
-I binary: Specifies the input file format as binary. This tellsavr-objcopyto interpret the source file as a raw binary. -
-O ihex: Specifies the output file format as Intel hex. The result will be an Intel hex formatted file, which is suitable for merging or programming into microcontroller memory. -
%4\%3.X.production.bin.signature.bin: The input file for the conversion. This is the raw binary signature produced by the previous script (%3: project name,%4: output directory) -
%4\%3.X.production.bin.signature.hex: The output file for the conversion. This is the resulting Intel hex file containing the signature, ready for merging into the application hex.
-
-
Embed Signature into Application Hex:This command uses Hexmate to merge the shifted digital signature, the main application code and upper application space (like CRC/config) into a single output hex file with the digital signature in its designated address range, preparing it for deployment as a signed image.hexmate r0-3FsFFBC,%4\%3.X.production.bin.signature.hex r0-FFBB,%4\%3.X.production.hex rFFFC-FFFFFFFF,%4\%3.X.production.hex -O%4\%3.X.production.hex-
hexmate: Invokes the Hexmate tool, which is used for manipulating and merging Intel hex files for Microchip devices. -
r0-3FsFFBC,%4\%3.X.production.bin.signature.hex: Reads the address range from0x00to0x3Fand then shifts it to start at0xFFBCfrom the input signature hex file. -r0-3F: selects bytes 0x00 to 0x3F from the signature hex (the binary signature). -sFFBC: shifts this block to be located at0xFFBC(the signature area in the final application image). -%4\%3.X.production.bin.signature.hex: the signature hex file (output from previous steps). -
r0-FFBB,%4\%3.X.production.hex: Reads address range from0x00to0xFFBBfrom the main application hex file. This is the bulk of the existing application firmware up to (but not including) the signature field. -
rFFFC-FFFFFFFF,%4\%3.X.production.hex: Reads from address0xFFFCto0xFFFFFFFFfrom the application hex file, which commonly includes metadata such as Cyclic Redundancy Check (CRC), reset vectors or Configuration bits. -
-O%4\%3.X.production.hex: Specifies the output file, writing the final merged and signed hex image back to%4\%3.X.production.hex.
-
-
Finalize Unimplemented Flash Range: Final step is to fill any remaining
unused Flash regions, including CRC locations, with 0xFF for clean and consistent
memory. This command fills all unimplemented or unused Flash memory locations in the
signed hex file’s address range 0x8000–0xFFFF with 0xFF, ensuring consistent values
for unused application memory areas.
This command fills all unimplemented or unused Flash memory locations in the signed hex file’s address range 0x8000–0xFFFF with 0xFF, ensuring consistent values for unused application memory areas.hexmate r0-FFFFFFFF,%4\%3.X.production.hex -O%4\%3.X.production.hex -FILL=w1:0xFF@0x8000:0xFFFF -
Remove Temporary Files: This command deletes all intermediate files created
during the process to conserve storage and maintain workspace cleanliness.
del %4\%3.X.production.bin.signature.hex del %4\%3.X.production.bin.signature.bin del %4\%3.X.production.bin.signature.der del %4\temp_original_copy.X.production.hex del %4\%3.X.production.bin
