diff options
Diffstat (limited to 'src/img4.c')
-rw-r--r-- | src/img4.c | 275 |
1 files changed, 182 insertions, 93 deletions
@@ -26,6 +26,7 @@ #include "common.h" #include "img4.h" +#include "endianness.h" #define ASN1_PRIVATE 0xc0 #define ASN1_PRIMITIVE_TAG 0x1f @@ -203,7 +204,7 @@ static void asn1_write_element(unsigned char **p, unsigned int *length, unsigned } } break; default: - fprintf(stderr, "ERROR: %s: type %02x is not implemented\n", __func__, type); + logger(LL_ERROR, "%s: type %02x is not implemented\n", __func__, type); return; } } @@ -290,6 +291,7 @@ static const char *_img4_get_component_tag(const char *compname) { "Ap,AudioPowerAttachChime", "aupr" }, { "Ap,BootabilityBrainTrustCache", "trbb" }, { "Ap,CIO", "ciof" }, + { "Ap,DCP2", "dcp2" }, { "Ap,HapticAssets", "hpas" }, { "Ap,LocalBoot", "lobo" }, { "Ap,LocalPolicy", "lpol" }, @@ -299,8 +301,13 @@ static const char *_img4_get_component_tag(const char *compname) { "Ap,RestoreANE2", "ran2" }, { "Ap,RestoreANE3", "ran3" }, { "Ap,RestoreCIO", "rcio" }, + { "Ap,RestoreDCP2", "rdc2", }, { "Ap,RestoreTMU", "rtmu" }, { "Ap,Scorpius", "scpf" }, + { "Ap,RestoreSecureM3Firmware", "rsm3" }, + { "Ap,RestoreSecurePageTableMonitor", "rspt" }, + { "Ap,RestoreTrustedExecutionMonitor", "rtrx" }, + { "Ap,RestorecL4", "rxcl" }, { "Ap,SystemVolumeCanonicalMetadata", "msys" }, { "Ap,TMU", "tmuf" }, { "Ap,VolumeUUID", "vuid" }, @@ -395,7 +402,7 @@ static const char *_img4_get_component_tag(const char *compname) return NULL; } -int img4_stitch_component(const char* component_name, const unsigned char* component_data, unsigned int component_size, plist_t tss_response, unsigned char** img4_data, unsigned int *img4_size) +int img4_stitch_component(const char* component_name, const void* component_data, size_t component_size, plist_t parameters, plist_t tss_response, void** img4_data, size_t *img4_size) { unsigned char* magic_header = NULL; unsigned int magic_header_size = 0; @@ -414,130 +421,212 @@ int img4_stitch_component(const char* component_name, const unsigned char* compo } if (tss_response_get_ap_img4_ticket(tss_response, &blob, &blob_size) != 0) { - error("ERROR: %s: Failed to get ApImg4Ticket from TSS response\n", __func__); + logger(LL_ERROR, "%s: Failed to get ApImg4Ticket from TSS response\n", __func__); return -1; } - info("Personalizing IMG4 component %s...\n", component_name); + logger(LL_INFO, "Personalizing IMG4 component %s...\n", component_name); /* first we need check if we have to change the tag for the given component */ const void *tag = asn1_find_element(1, ASN1_IA5_STRING, component_data); if (tag) { - debug("Tag found\n"); - if (strcmp(component_name, "RestoreKernelCache") == 0) { - memcpy((void*)tag, "rkrn", 4); - } else if (strcmp(component_name, "RestoreDeviceTree") == 0) { - memcpy((void*)tag, "rdtr", 4); - } else if (strcmp(component_name, "RestoreSEP") == 0) { - memcpy((void*)tag, "rsep", 4); - } else if (strcmp(component_name, "RestoreLogo") == 0) { - memcpy((void*)tag, "rlgo", 4); - } else if (strcmp(component_name, "RestoreTrustCache") == 0) { - memcpy((void*)tag, "rtsc", 4); - } else if (strcmp(component_name, "RestoreDCP") == 0) { - memcpy((void*)tag, "rdcp", 4); - } else if (strcmp(component_name, "Ap,RestoreTMU") == 0) { - memcpy((void*)tag, "rtmu", 4); - } else if (strcmp(component_name, "Ap,RestoreCIO") == 0) { - memcpy((void*)tag, "rcio", 4); - } else if (strcmp(component_name, "Ap,DCP2") == 0) { - memcpy((void*)tag, "dcp2", 4); + logger(LL_DEBUG, "Tag found\n"); + const char* matches[] = { + "RestoreKernelCache", + "RestoreDeviceTree", + "RestoreSEP", + "RestoreLogo", + "RestoreTrustCache", + "RestoreDCP", + "Ap,RestoreDCP2", + "Ap,RestoreTMU", + "Ap,RestoreCIO", + "Ap,DCP2", + "Ap,RestoreSecureM3Firmware", + "Ap,RestoreSecurePageTableMonitor", + "Ap,RestoreTrustedExecutionMonitor", + "Ap,RestorecL4", + NULL + }; + int i = 0; + while (matches[i]) { + if (!strcmp(matches[i], component_name)) { + const char* comptag = _img4_get_component_tag(component_name); + if (comptag) { + memcpy((void*)tag, comptag, 4); + } else { + logger(LL_WARNING, "Cannot find tag for component '%s'\n", component_name); + } + break; + } + i++; } + } else { + logger(LL_ERROR, "Personalization failed for component '%s': Tag not found\n", component_name); + return -1; } // check if we have a *-TBM entry for the given component unsigned char *additional_data = NULL; unsigned int additional_size = 0; char *tbm_key = malloc(strlen(component_name) + 5); - sprintf(tbm_key, "%s-TBM", component_name); + snprintf(tbm_key, strlen(component_name)+5, "%s-TBM", component_name); plist_t tbm_dict = plist_dict_get_item(tss_response, tbm_key); free(tbm_key); + uint64_t ucon_size = 0; + const char* ucon_data = NULL; + uint64_t ucer_size = 0; + const char* ucer_data = NULL; if (tbm_dict) { plist_t dt = plist_dict_get_item(tbm_dict, "ucon"); if (!dt) { - error("ERROR: %s: Missing ucon node in %s-TBM dictionary\n", __func__, component_name); + logger(LL_ERROR, "%s: Missing ucon node in %s-TBM dictionary\n", __func__, component_name); return -1; } - uint64_t ucon_size = 0; - const char* ucon_data = plist_get_data_ptr(dt, &ucon_size); + ucon_data = plist_get_data_ptr(dt, &ucon_size); if (!ucon_data) { - error("ERROR: %s: Missing ucon data in %s-TBM dictionary\n", __func__, component_name); + logger(LL_ERROR, "%s: Missing ucon data in %s-TBM dictionary\n", __func__, component_name); return -1; } dt = plist_dict_get_item(tbm_dict, "ucer"); if (!dt) { - error("ERROR: %s: Missing ucer data node in %s-TBM dictionary\n", __func__, component_name); + logger(LL_ERROR, "%s: Missing ucer data node in %s-TBM dictionary\n", __func__, component_name); return -1; } - uint64_t ucer_size = 0; - const char* ucer_data = plist_get_data_ptr(dt, &ucer_size); + ucer_data = plist_get_data_ptr(dt, &ucer_size); if (!ucer_data) { - error("ERROR: %s: Missing ucer data in %s-TBM dictionary\n", __func__, component_name); + logger(LL_ERROR, "%s: Missing ucer data in %s-TBM dictionary\n", __func__, component_name); return -1; } + } - unsigned char *im4rset = (unsigned char*)malloc(16 + 8 + 8 + ucon_size + 16 + 8 + 8 + ucer_size + 16); + int nonce_slot_required = plist_dict_get_bool(parameters, "RequiresNonceSlot") && (!strcmp(component_name, "SEP") || !strcmp(component_name, "SepStage1") || !strcmp(component_name, "LLB")); + + if (ucon_data || ucer_data || nonce_slot_required) { + size_t im4r_size = 16; + if (ucon_data) { + im4r_size += 8 + 8 + ucon_size + 16; + } + if (ucer_data) { + im4r_size += 8 + 8 + ucer_size + 16; + } + if (nonce_slot_required) { + im4r_size += 16; + } + unsigned char *im4rset = (unsigned char*)malloc(im4r_size); unsigned char *p_im4rset = im4rset; unsigned int im4rlen = 0; + // ----------- anid/snid ------- + if (nonce_slot_required) { + const char* tag_name = NULL; + uint64_t tag_value = 0; + if (!strcmp(component_name, "SEP") || !strcmp(component_name, "SepStage1")) { + tag_name = "snid"; + tag_value = 2; + if (plist_dict_get_item(parameters, "SepNonceSlotID")) { + tag_value = plist_dict_get_uint(parameters, "SepNonceSlotID"); + } + } else { + tag_name = "anid"; + tag_value = 0; + if (plist_dict_get_item(parameters, "ApNonceSlotID")) { + tag_value = plist_dict_get_uint(parameters, "ApNonceSlotID"); + } + } + // write priv anid/snid element + asn1_write_priv_element(&p_im4rset, &im4rlen, __bswap_32(*(uint32_t*)tag_name)); + // write anid/snid IA5STRING and anid/snid value + unsigned char inner_seq[16]; + unsigned char *p_inner_seq = &inner_seq[0]; + unsigned int inner_seq_hdr_len = 0; + asn1_write_element(&p_inner_seq, &inner_seq_hdr_len, ASN1_IA5_STRING, (void*)tag_name, -1); + asn1_write_element(&p_inner_seq, &inner_seq_hdr_len, ASN1_INTEGER, (void*)&tag_value, -1); + + // write anid/snid sequence + unsigned char elem_seq[8]; + unsigned char *p = &elem_seq[0]; + unsigned int seq_hdr_len = 0; + asn1_write_element_header(ASN1_SEQUENCE | ASN1_CONSTRUCTED, inner_seq_hdr_len, &p, &seq_hdr_len); + + // add size to priv anid/snid element + asn1_write_size(inner_seq_hdr_len + seq_hdr_len, &p_im4rset, &im4rlen); + + // put it together + memcpy(p_im4rset, elem_seq, seq_hdr_len); + p_im4rset += seq_hdr_len; + im4rlen += seq_hdr_len; + memcpy(p_im4rset, inner_seq, inner_seq_hdr_len); + p_im4rset += inner_seq_hdr_len; + im4rlen += inner_seq_hdr_len; + } + // ----------- ucon ------------ - // write priv ucon element - asn1_write_priv_element(&p_im4rset, &im4rlen, *(uint32_t*)"nocu"); - - // write ucon IA5STRING and ucon data - unsigned char ucon_seq[16]; - unsigned char *p_ucon_seq = &ucon_seq[0]; - unsigned int ucon_seq_hdr_len = 0; - asn1_write_element(&p_ucon_seq, &ucon_seq_hdr_len, ASN1_IA5_STRING, (void*)"ucon", -1); - asn1_write_element_header(ASN1_OCTET_STRING, ucon_size, &p_ucon_seq, &ucon_seq_hdr_len); - - // write ucon sequence - unsigned char elem_seq[8]; - unsigned char *p = &elem_seq[0]; - unsigned int seq_hdr_len = 0; - asn1_write_element_header(ASN1_SEQUENCE | ASN1_CONSTRUCTED, ucon_seq_hdr_len + ucon_size, &p, &seq_hdr_len); - - // add size to priv ucon element - asn1_write_size(ucon_seq_hdr_len + ucon_size + seq_hdr_len, &p_im4rset, &im4rlen); - - // put it together - memcpy(p_im4rset, elem_seq, seq_hdr_len); - p_im4rset += seq_hdr_len; - im4rlen += seq_hdr_len; - memcpy(p_im4rset, ucon_seq, ucon_seq_hdr_len); - p_im4rset += ucon_seq_hdr_len; - im4rlen += ucon_seq_hdr_len; - memcpy(p_im4rset, ucon_data, ucon_size); - p_im4rset += ucon_size; - im4rlen += ucon_size; + if (ucon_data) { + // write priv ucon element + asn1_write_priv_element(&p_im4rset, &im4rlen, *(uint32_t*)"nocu"); + + // write ucon IA5STRING and ucon data header + unsigned char inner_seq[16]; + unsigned char *p_inner_seq = &inner_seq[0]; + unsigned int inner_seq_hdr_len = 0; + asn1_write_element(&p_inner_seq, &inner_seq_hdr_len, ASN1_IA5_STRING, (void*)"ucon", -1); + asn1_write_element_header(ASN1_OCTET_STRING, ucon_size, &p_inner_seq, &inner_seq_hdr_len); + + // write ucon sequence + unsigned char elem_seq[8]; + unsigned char *p = &elem_seq[0]; + unsigned int seq_hdr_len = 0; + asn1_write_element_header(ASN1_SEQUENCE | ASN1_CONSTRUCTED, inner_seq_hdr_len + ucon_size, &p, &seq_hdr_len); + + // add size to priv ucon element + asn1_write_size(inner_seq_hdr_len + ucon_size + seq_hdr_len, &p_im4rset, &im4rlen); + + // put it together + memcpy(p_im4rset, elem_seq, seq_hdr_len); + p_im4rset += seq_hdr_len; + im4rlen += seq_hdr_len; + memcpy(p_im4rset, inner_seq, inner_seq_hdr_len); + p_im4rset += inner_seq_hdr_len; + im4rlen += inner_seq_hdr_len; + // write ucon data + memcpy(p_im4rset, ucon_data, ucon_size); + p_im4rset += ucon_size; + im4rlen += ucon_size; + } // ----------- ucer ------------ - // write priv ucer element - asn1_write_priv_element(&p_im4rset, &im4rlen, *(uint32_t*)"recu"); - - // write ucon IA5STRING and ucer data - unsigned char ucer_seq[16]; - unsigned char *p_ucer_seq = &ucer_seq[0]; - unsigned int ucer_seq_hdr_len = 0; - asn1_write_element(&p_ucer_seq, &ucer_seq_hdr_len, ASN1_IA5_STRING, (void*)"ucer", -1); - asn1_write_element_header(ASN1_OCTET_STRING, ucer_size, &p_ucer_seq, &ucer_seq_hdr_len); - - p = &elem_seq[0]; - seq_hdr_len = 0; - asn1_write_element_header(ASN1_SEQUENCE | ASN1_CONSTRUCTED, ucer_seq_hdr_len + ucer_size, &p, &seq_hdr_len); - - // add size to priv ucer element - asn1_write_size(ucer_seq_hdr_len + ucer_size + seq_hdr_len, &p_im4rset, &im4rlen); - - // put it together - memcpy(p_im4rset, elem_seq, seq_hdr_len); - p_im4rset += seq_hdr_len; - im4rlen += seq_hdr_len; - memcpy(p_im4rset, ucer_seq, ucer_seq_hdr_len); - p_im4rset += ucer_seq_hdr_len; - im4rlen += ucer_seq_hdr_len; - memcpy(p_im4rset, ucer_data, ucer_size); - p_im4rset += ucer_size; - im4rlen += ucer_size; + if (ucer_data) { + // write priv ucer element + asn1_write_priv_element(&p_im4rset, &im4rlen, *(uint32_t*)"recu"); + + // write ucer IA5STRING and ucer data header + unsigned char inner_seq[16]; + unsigned char *p_inner_seq = &inner_seq[0]; + unsigned int inner_seq_hdr_len = 0; + asn1_write_element(&p_inner_seq, &inner_seq_hdr_len, ASN1_IA5_STRING, (void*)"ucer", -1); + asn1_write_element_header(ASN1_OCTET_STRING, ucer_size, &p_inner_seq, &inner_seq_hdr_len); + + // write ucer sequence + unsigned char elem_seq[8]; + unsigned char *p = &elem_seq[0]; + unsigned int seq_hdr_len = 0; + asn1_write_element_header(ASN1_SEQUENCE | ASN1_CONSTRUCTED, inner_seq_hdr_len + ucer_size, &p, &seq_hdr_len); + + // add size to priv ucer element + asn1_write_size(inner_seq_hdr_len + ucer_size + seq_hdr_len, &p_im4rset, &im4rlen); + + // put it together + memcpy(p_im4rset, elem_seq, seq_hdr_len); + p_im4rset += seq_hdr_len; + im4rlen += seq_hdr_len; + memcpy(p_im4rset, inner_seq, inner_seq_hdr_len); + p_im4rset += inner_seq_hdr_len; + im4rlen += inner_seq_hdr_len; + // write ucer data + memcpy(p_im4rset, ucer_data, ucer_size); + p_im4rset += ucer_size; + im4rlen += ucer_size; + } // now construct IM4R @@ -606,7 +695,7 @@ int img4_stitch_component(const char* component_name, const unsigned char* compo free(img4header); } free(additional_data); - error("ERROR: out of memory when personalizing IMG4 component %s\n", component_name); + logger(LL_ERROR, "out of memory when personalizing IMG4 component %s\n", component_name); return -1; } p = outbuf; @@ -748,7 +837,7 @@ static void _manifest_write_component(unsigned char **p, unsigned int *length, c tbmtag = "tbmr"; } if (!tbmtag) { - error("ERROR: Unexpected TMBDigests for comp '%s'\n", tag); + logger(LL_ERROR, "Unexpected TMBDigests for comp '%s'\n", tag); } else { _manifest_write_key_value(&tmp, &tmp_len, tbmtag, ASN1_OCTET_STRING, (void*)data, datalen); } @@ -841,10 +930,10 @@ int img4_create_local_manifest(plist_t request, plist_t build_identity, plist_t* comp = _img4_get_component_tag(key); } if (!comp) { - debug("DEBUG: %s: Unhandled component '%s'\n", __func__, key); + logger(LL_DEBUG, "%s: Unhandled component '%s'\n", __func__, key); _manifest_write_component(&p, &length, key, val); } else { - debug("DEBUG: found component %s (%s)\n", comp, key); + logger(LL_DEBUG, "found component %s (%s)\n", comp, key); _manifest_write_component(&p, &length, comp, val); } } |