summaryrefslogtreecommitdiffstats
path: root/src/img4.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/img4.c')
-rw-r--r--src/img4.c275
1 files changed, 182 insertions, 93 deletions
diff --git a/src/img4.c b/src/img4.c
index cfd3c93..732ef69 100644
--- a/src/img4.c
+++ b/src/img4.c
@@ -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);
}
}