diff options
author | Dave Heller <hellerda@us.ibm.com> | 2017-07-29 12:50:00 -0400 |
---|---|---|
committer | Dave Heller <hellerda@us.ibm.com> | 2017-07-29 12:50:00 -0400 |
commit | 8706c1ec90a2fec4cb79fea1973374ba37a26d36 (patch) | |
tree | 8051bc06276834d72c0f87c507bb4897663d854e | |
parent | 0144ed1f3ba0faae7d0c9047c02ebd75ea5f9215 (diff) | |
download | sb-signing-utils-8706c1ec90a2fec4cb79fea1973374ba37a26d36.tar.gz sb-signing-utils-8706c1ec90a2fec4cb79fea1973374ba37a26d36.zip |
Add --validate and --verify options to crtSignedContainer.sh
-rw-r--r-- | container.c | 18 | ||||
-rw-r--r-- | create-container.c | 21 | ||||
-rwxr-xr-x | crtSignedContainer.sh | 34 | ||||
-rw-r--r-- | print-container.c | 49 |
4 files changed, 93 insertions, 29 deletions
diff --git a/container.c b/container.c index ba42234..1f180a5 100644 --- a/container.c +++ b/container.c @@ -28,7 +28,7 @@ extern char *progname; -extern bool verbose; +extern bool verbose, debug; extern int wrap; #define die(status, msg, ...) \ @@ -43,10 +43,8 @@ extern int wrap; if (verbose) fprintf(stdout, "--> %s: " msg "\n", progname, \ __VA_ARGS__); -void verbose_print(char *lead, unsigned char *buffer, size_t buflen) +void hex_print(char *lead, unsigned char *buffer, size_t buflen) { - if (!verbose) - return; unsigned int i, indent = 4; char prelead[100]; snprintf(prelead, 100, "--> %s: ", progname); @@ -66,6 +64,18 @@ void verbose_print(char *lead, unsigned char *buffer, size_t buflen) fprintf(stdout, "\n"); } +void verbose_print(char *lead, unsigned char *buffer, size_t buflen) +{ + if (verbose) + hex_print(lead, buffer, buflen); +} + +void debug_print(char *lead, unsigned char *buffer, size_t buflen) +{ + if (debug) + hex_print(lead, buffer, buflen); +} + int isValidHex(char *input, int len) { int r; size_t maxlen = 512; // sane limit diff --git a/create-container.c b/create-container.c index 75106d6..65c5fc2 100644 --- a/create-container.c +++ b/create-container.c @@ -442,6 +442,8 @@ int main(int argc, char* argv[]) ph->ver_alg.version = cpu_to_be16(1); ph->ver_alg.hash_alg = 1; ph->ver_alg.sig_alg = 1; + + // Set code-start-offset. if (params.hw_cs_offset) { if (!isValidHex(params.hw_cs_offset, 4)) die(EX_DATAERR, "%s", @@ -454,6 +456,8 @@ int main(int argc, char* argv[]) ph->code_start_offset = 0; } ph->reserved = 0; + + // Set flags. if (params.hw_flags) { if (!isValidHex(params.hw_flags, 4)) die(EX_DATAERR, "%s", @@ -472,6 +476,8 @@ int main(int argc, char* argv[]) memset(pd->hw_sig_a, 0, sizeof(ecc_signature_t)); memset(pd->hw_sig_b, 0, sizeof(ecc_signature_t)); memset(pd->hw_sig_c, 0, sizeof(ecc_signature_t)); + + // Write the HW signatures. if (params.hw_sigfn_a) { getSigRaw(&sigraw, params.hw_sigfn_a); verbose_print((char *) "signature A = ", sigraw, sizeof(sigraw)); @@ -490,6 +496,8 @@ int main(int argc, char* argv[]) memset(pd->sw_pkey_p, 0, sizeof(ecc_key_t)); memset(pd->sw_pkey_q, 0, sizeof(ecc_key_t)); memset(pd->sw_pkey_r, 0, sizeof(ecc_key_t)); + + // Write the FW keys. if (params.sw_keyfn_p) { getPublicKeyRaw(&pubkeyraw, params.sw_keyfn_p); verbose_print((char *) "pubkey P = ", pubkeyraw, sizeof(pubkeyraw) - 1); @@ -510,12 +518,15 @@ int main(int argc, char* argv[]) } debug_msg("sw_key_count = %u", ph->sw_key_count); ph->payload_size = cpu_to_be64(ph->sw_key_count * sizeof(ecc_key_t)); + + // Calculate the SW keys hash. p = SHA512(pd->sw_pkey_p, sizeof(ecc_key_t) * ph->sw_key_count, md); if (!p) die(EX_SOFTWARE, "%s", "Cannot get SHA512"); memcpy(ph->payload_hash, md, sizeof(sha2_hash_t)); verbose_print((char *) "SW keys hash = ", md, sizeof(md)); + // Dump the Prefix header. if (params.prhdrfn) writeHdr((void *) ph, params.prhdrfn, PREFIX_HDR); @@ -524,6 +535,8 @@ int main(int argc, char* argv[]) swh->ver_alg.version = cpu_to_be16(1); swh->ver_alg.hash_alg = 1; swh->ver_alg.sig_alg = 1; + + // Set code-start-offset. if (params.sw_cs_offset) { if (!isValidHex(params.sw_cs_offset, 4)) die(EX_DATAERR, "%s", @@ -536,6 +549,8 @@ int main(int argc, char* argv[]) swh->code_start_offset = 0; } swh->reserved = 0; + + // Set flags. if (params.sw_flags) { if (!isValidHex(params.sw_flags, 4)) die(EX_DATAERR, "%s", @@ -549,12 +564,15 @@ int main(int argc, char* argv[]) } swh->reserved_0 = 0; swh->payload_size = cpu_to_be64(payload_st.st_size); + + // Calculate the payload hash. p = SHA512(infile, payload_st.st_size, md); if (!p) die(EX_SOFTWARE, "%s", "Cannot get SHA512"); memcpy(swh->payload_hash, md, sizeof(sha2_hash_t)); verbose_print((char *) "Payload hash = ", md, sizeof(md)); + // Dump the Software header. if (params.swhdrfn) writeHdr((void *) swh, params.swhdrfn, SOFTWARE_HDR); @@ -562,6 +580,8 @@ int main(int argc, char* argv[]) memset(ssig->sw_sig_p, 0, sizeof(ecc_signature_t)); memset(ssig->sw_sig_q, 0, sizeof(ecc_signature_t)); memset(ssig->sw_sig_r, 0, sizeof(ecc_signature_t)); + + // Write the HW signatures. if (params.sw_sigfn_p) { getSigRaw(&sigraw, params.sw_sigfn_p); verbose_print((char *) "signature P = ", sigraw, sizeof(sigraw)); @@ -578,6 +598,7 @@ int main(int argc, char* argv[]) memcpy(ssig->sw_sig_r, sigraw, sizeof(ecc_key_t)); } + // Print container stats. size = (uint8_t*) ph - (uint8_t *) c; offset = (uint8_t*) c - (uint8_t *) c; verbose_msg("HW header size = %4u (%#06x) at offset %4u (%#06x)", diff --git a/crtSignedContainer.sh b/crtSignedContainer.sh index b84a030..39d2c9b 100755 --- a/crtSignedContainer.sh +++ b/crtSignedContainer.sh @@ -4,6 +4,7 @@ VERBOSE="" DEBUG="" WRAP="" +RC=0 P=${0##*/} @@ -26,6 +27,9 @@ usage () { echo " -o, --code-start-offset code start offset for software header in hex" echo " -f, --flags prefix header flags in hex" echo " -e, --eyeCatch name or identifier of the module being built" + echo " --validate validate the container after build" + echo " --verify verify the container after build, against the provided" + echo " value, or filename containing value, of the HW Keys hash" echo "" exit 1 } @@ -97,12 +101,14 @@ for arg in "$@"; do "--protectedPayload") set -- "$@" "-l" ;; "--out") set -- "$@" "-i" ;; "--eyeCatch") set -- "$@" "-e" ;; + "--validate") set -- "$@" "-8" ;; + "--verify") set -- "$@" "-9" ;; *) set -- "$@" "$arg" esac done # Process command-line arguments -while getopts ?dvw:a:b:c:p:q:r:f:o:l:i:e: opt +while getopts ?dvw:a:b:c:p:q:r:f:o:l:i:e:89: opt do case "$opt" in v) VERBOSE="TRUE";; @@ -119,6 +125,8 @@ do l) PAYLOAD="`echo $OPTARG`";; i) OUTPUT="`echo $OPTARG`";; e) eyeCatch="`echo $OPTARG`";; + 8) VALIDATE="TRUE";; + 9) VERIFY="`echo $OPTARG`";; h|\?) usage;; esac done @@ -176,6 +184,8 @@ HW_KEY_ARGS="" SW_KEY_ARGS="" HW_SIG_ARGS="" SW_SIG_ARGS="" +VERIFY_ARGS="" +DEBUG_ARGS="" ADDL_ARGS="" [ -n "$HW_KEY_A" ] && HW_KEY_ARGS="$HW_KEY_ARGS -a $HW_KEY_A" @@ -185,17 +195,21 @@ ADDL_ARGS="" [ -n "$SW_KEY_Q" ] && SW_KEY_ARGS="$SW_KEY_ARGS -q $SW_KEY_Q" [ -n "$SW_KEY_R" ] && SW_KEY_ARGS="$SW_KEY_ARGS -r $SW_KEY_R" +[ -n "$VERBOSE" ] && DEBUG_ARGS="$DEBUG_ARGS -v" +[ -n "$DEBUG" ] && DEBUG_ARGS="$DEBUG_ARGS -d" +[ -n "$WRAP" ] && DEBUG_ARGS="$DEBUG_ARGS -w $WRAP" [ -n "$HW_FLAGS" ] && ADDL_ARGS="$ADDL_ARGS --hw-flags $HW_FLAGS" [ -n "$CS_OFFSET" ] && ADDL_ARGS="$ADDL_ARGS --sw-cs-offset $CS_OFFSET" -[ -n "$VERBOSE" ] && ADDL_ARGS="$ADDL_ARGS -v" -[ -n "$DEBUG" ] && ADDL_ARGS="$ADDL_ARGS -d" -[ -n "$WRAP" ] && ADDL_ARGS="$ADDL_ARGS -w $WRAP" + +[ -n "$VALIDATE" ] && VERIFY_ARGS="$VERIFY_ARGS --validate" +[ -n "$VERIFY" ] && VERIFY_ARGS="$VERIFY_ARGS --verify $VERIFY" # Build enough of the container to create the Prefix and Software headers echo "--> $P: Generating signing requests..." create-container $HW_KEY_ARGS $SW_KEY_ARGS \ --payload $PAYLOAD --imagefile $OUTPUT \ --dumpPrefixHdr $T/prefix_hdr --dumpSwHdr $T/software_hdr \ + $DEBUG_ARGS \ $ADDL_ARGS # Sign the Prefix header (all 3 HW keys are required) @@ -264,12 +278,20 @@ if [ -n "$HW_SIG_ARGS" -o -n "$SW_SIG_ARGS" ]; then create-container $HW_KEY_ARGS $SW_KEY_ARGS \ $HW_SIG_ARGS $SW_SIG_ARGS \ --payload $PAYLOAD --imagefile $OUTPUT \ + $DEBUG_ARGS \ $ADDL_ARGS else echo "--> $P: No signatures available." fi -echo "--> $P: Done." +echo "--> $P: Container build completed." + +# Validate, verify the container. +if [ -n "$VALIDATE" -o -n "$VERIFY" ]; then + echo + print-container --imagefile $OUTPUT --no-print $VERIFY_ARGS $DEBUG_ARGS + RC=$? +fi # Cleanup if [ $KEEP_CACHE == false ]; then @@ -283,3 +305,5 @@ if [ $KEEP_CACHE == false ]; then echo "--> $P: Not removing cache dir: $T" fi fi + +exit $RC diff --git a/print-container.c b/print-container.c index 7fb088a..d692705 100644 --- a/print-container.c +++ b/print-container.c @@ -162,6 +162,7 @@ static void display_container(struct parsed_stb_container c) sizeof(c.c->hw_pkey_b)); print_bytes((char *) "hw_pkey_c: ", (uint8_t *) c.c->hw_pkey_c, sizeof(c.c->hw_pkey_c)); + p = SHA512(c.c->hw_pkey_a, sizeof(ecc_key_t) * 3, md); if (!p) die(EX_SOFTWARE, "%s", "Cannot get SHA512"); @@ -246,7 +247,7 @@ static bool validate_container(struct parsed_stb_container c, int fdin) p = SHA512((uint8_t *) c.ph, sizeof(ROM_prefix_header_raw), md); if (!p) die(EX_SOFTWARE, "%s", "Cannot get SHA512"); - print_bytes((char *) "PR header hash = ", (uint8_t *) md, + if (verbose) print_bytes((char *) "PR header hash = ", (uint8_t *) md, SHA512_DIGEST_LENGTH); // Verify HW key sigs. @@ -256,13 +257,13 @@ static bool validate_container(struct parsed_stb_container c, int fdin) c.pd->hw_sig_b, c.c->hw_pkey_b) && status; status = verify_signature("HW sig C", md, SHA512_DIGEST_LENGTH, c.pd->hw_sig_c, c.c->hw_pkey_c) && status; - printf("\n"); + if (verbose) printf("\n"); // Get SW header hash. p = SHA512((uint8_t *) c.sh, sizeof(ROM_sw_header_raw), md); if (!p) die(EX_SOFTWARE, "%s", "Cannot get SHA512"); - print_bytes((char *) "SW header hash = ", (uint8_t *) md, + if (verbose) print_bytes((char *) "SW header hash = ", (uint8_t *) md, SHA512_DIGEST_LENGTH); // Verify SW key sigs. @@ -275,36 +276,41 @@ static bool validate_container(struct parsed_stb_container c, int fdin) if (c.ph->sw_key_count >= 3) status = verify_signature("SW sig R", md, SHA512_DIGEST_LENGTH, c.ssig->sw_sig_r, c.pd->sw_pkey_r) && status; - printf("\n"); + if (verbose) printf("\n"); // Verify Payload hash. status = getPayloadHash(fdin, md) && status; - print_bytes((char *) "Payload hash = ", (uint8_t *) md, + if (verbose) print_bytes((char *) "Payload hash = ", (uint8_t *) md, SHA512_DIGEST_LENGTH); if (memcmp((uint8_t *) c.sh->payload_hash, md, SHA512_DIGEST_LENGTH)) { - printf("Payload hash does not agree with value in SW header: MISMATCH\n"); + if (verbose) + printf("Payload hash does not agree with value in SW header: MISMATCH\n"); status = false; } else { - printf("Payload hash agrees with value in SW header: VERIFIED ./\n"); + if (verbose) + printf("Payload hash agrees with value in SW header: VERIFIED ./\n"); status = status && true; } - printf("\n"); + if (verbose) printf("\n"); // Verify SW keys hash. p = SHA512(c.pd->sw_pkey_p, sizeof(ecc_key_t) * c.ph->sw_key_count, md); if (!p) die(EX_SOFTWARE, "%s", "Cannot get SHA512"); - print_bytes((char *) "SW keys hash = ", (uint8_t *) md, + if (verbose) print_bytes((char *) "SW keys hash = ", (uint8_t *) md, SHA512_DIGEST_LENGTH); if (memcmp((uint8_t *) c.ph->payload_hash, md, SHA512_DIGEST_LENGTH)) { - printf("SW keys hash does not agree with value in Prefix header: MISMATCH\n"); + if (verbose) + printf("SW keys hash does not agree with value in Prefix header: MISMATCH\n"); status = false; } else { - printf("SW keys hash agrees with value in Prefix header: VERIFIED ./\n"); + if (verbose) + printf("SW keys hash agrees with value in Prefix header: VERIFIED ./\n"); status = status && true; } + if (verbose) printf("\n"); return status; } @@ -314,23 +320,25 @@ static bool verify_container(struct parsed_stb_container c, char * verify) void *md = alloca(SHA512_DIGEST_LENGTH); void *p; - printf("\n"); p = SHA512(c.c->hw_pkey_a, sizeof(ecc_key_t) * 3, md); if (!p) die(EX_SOFTWARE, "%s", "Cannot get SHA512"); - print_bytes((char *) "HW keys hash = ", (uint8_t *) md, + if (verbose) print_bytes((char *) "HW keys hash = ", (uint8_t *) md, SHA512_DIGEST_LENGTH); void *md_verify = alloca(SHA512_DIGEST_LENGTH); getVerificationHash(verify, md_verify, SHA512_DIGEST_LENGTH); if (memcmp((uint8_t *) md_verify, md, SHA512_DIGEST_LENGTH )) { - printf("HW keys hash does not agree with provided value: MISMATCH\n"); + if (verbose) + printf("HW keys hash does not agree with provided value: MISMATCH\n"); } else { - printf("HW keys hash agrees with provided value: VERIFIED ./\n"); + if (verbose) + printf("HW keys hash agrees with provided value: VERIFIED ./\n"); status = true; } + if (verbose) printf("\n"); return status; } @@ -341,7 +349,7 @@ static bool verify_signature(const char *moniker, const unsigned char *dgst, bool status = false; // Convert the raw sig to a structure that can be handled by openssl. - verbose_print((char *) "Raw sig = ", (uint8_t *) sig_raw, + debug_print((char *) "Raw sig = ", (uint8_t *) sig_raw, sizeof(ecc_signature_t)); BIGNUM *r_bn = BN_new(); @@ -360,7 +368,7 @@ static bool verify_signature(const char *moniker, const unsigned char *dgst, #endif // Convert the raw key to a structure that can be handled by openssl. - verbose_print((char *) "Raw key = ", (uint8_t *) key_raw, + debug_print((char *) "Raw key = ", (uint8_t *) key_raw, sizeof(ecc_key_t)); EC_KEY *ec_key = EC_KEY_new(); @@ -394,10 +402,10 @@ static bool verify_signature(const char *moniker, const unsigned char *dgst, // Verify the signature. r = ECDSA_do_verify(dgst, dgst_len, ecdsa_sig, ec_key); if (r == 1) { - printf("%s is good: VERIFIED ./\n", moniker); + if (verbose) printf("%s is good: VERIFIED ./\n", moniker); status = true; } else if (r == 0) { - printf("%s FAILED to verify.\n", moniker); + if (verbose) printf("%s FAILED to verify.\n", moniker); status = false; } else { die(EX_SOFTWARE, "%s", "Cannot ECDSA_do_verify"); @@ -578,6 +586,7 @@ int main(int argc, char* argv[]) break; case 'w': wrap = atoi(optarg); + wrap = (wrap < 2) ? INT_MAX : wrap; break; case 's': print_stats = true; @@ -634,7 +643,7 @@ int main(int argc, char* argv[]) if ((validate_status != UNATTEMPTED) || (verify_status != UNATTEMPTED)) { - printf("\nContainer validity check %s. Container verification check %s.\n\n", + printf("Container validity check %s. Container verification check %s.\n\n", (validate_status == UNATTEMPTED) ? "not attempted" : ((validate_status == PASSED) ? "PASSED" : "FAILED"), |