Merge "fix(driver/auth): avoid NV counter upgrade without certificate validation" into integration

This commit is contained in:
Mark Dykes 2021-04-28 21:02:12 +02:00 committed by TrustedFirmware Code Review
commit 2ba56793d1
1 changed files with 34 additions and 13 deletions

View File

@ -222,19 +222,25 @@ static int auth_signature(const auth_method_param_sig_t *param,
* To protect the system against rollback, the platform includes a non-volatile
* counter whose value can only be increased. All certificates include a counter
* value that should not be lower than the value stored in the platform. If the
* value is larger, the counter in the platform must be updated to the new
* value.
* value is larger, the counter in the platform must be updated to the new value
* (provided it has been authenticated).
*
* Return: 0 = success, Otherwise = error
* Returns additionally,
* cert_nv_ctr -> NV counter value present in the certificate
* need_nv_ctr_upgrade = 0 -> platform NV counter upgrade is not needed
* need_nv_ctr_upgrade = 1 -> platform NV counter upgrade is needed
*/
static int auth_nvctr(const auth_method_param_nv_ctr_t *param,
const auth_img_desc_t *img_desc,
void *img, unsigned int img_len)
void *img, unsigned int img_len,
unsigned int *cert_nv_ctr,
bool *need_nv_ctr_upgrade)
{
char *p;
void *data_ptr = NULL;
unsigned int data_len, len, i;
unsigned int cert_nv_ctr, plat_nv_ctr;
unsigned int plat_nv_ctr;
int rc = 0;
/* Get the counter value from current image. The AM expects the IPM
@ -265,22 +271,20 @@ static int auth_nvctr(const auth_method_param_nv_ctr_t *param,
}
/* Convert to unsigned int. This code is for a little-endian CPU */
cert_nv_ctr = 0;
*cert_nv_ctr = 0;
for (i = 0; i < len; i++) {
cert_nv_ctr = (cert_nv_ctr << 8) | *p++;
*cert_nv_ctr = (*cert_nv_ctr << 8) | *p++;
}
/* Get the counter from the platform */
rc = plat_get_nv_ctr(param->plat_nv_ctr->cookie, &plat_nv_ctr);
return_if_error(rc);
if (cert_nv_ctr < plat_nv_ctr) {
if (*cert_nv_ctr < plat_nv_ctr) {
/* Invalid NV-counter */
return 1;
} else if (cert_nv_ctr > plat_nv_ctr) {
rc = plat_set_nv_ctr2(param->plat_nv_ctr->cookie,
img_desc, cert_nv_ctr);
return_if_error(rc);
} else if (*cert_nv_ctr > plat_nv_ctr) {
*need_nv_ctr_upgrade = true;
}
return 0;
@ -351,6 +355,10 @@ int auth_mod_verify_img(unsigned int img_id,
void *param_ptr;
unsigned int param_len;
int rc, i;
unsigned int cert_nv_ctr = 0;
bool need_nv_ctr_upgrade = false;
bool sig_auth_done = false;
const auth_method_param_nv_ctr_t *nv_ctr_param = NULL;
/* Get the image descriptor from the chain of trust */
img_desc = FCONF_GET_PROPERTY(tbbr, cot, img_id);
@ -376,10 +384,13 @@ int auth_mod_verify_img(unsigned int img_id,
case AUTH_METHOD_SIG:
rc = auth_signature(&auth_method->param.sig,
img_desc, img_ptr, img_len);
sig_auth_done = true;
break;
case AUTH_METHOD_NV_CTR:
rc = auth_nvctr(&auth_method->param.nv_ctr,
img_desc, img_ptr, img_len);
nv_ctr_param = &auth_method->param.nv_ctr;
rc = auth_nvctr(nv_ctr_param,
img_desc, img_ptr, img_len,
&cert_nv_ctr, &need_nv_ctr_upgrade);
break;
default:
/* Unknown authentication method */
@ -389,6 +400,16 @@ int auth_mod_verify_img(unsigned int img_id,
return_if_error(rc);
}
/*
* Do platform NV counter upgrade only if the certificate gets
* authenticated, and platform NV-counter upgrade is needed.
*/
if (need_nv_ctr_upgrade && sig_auth_done) {
rc = plat_set_nv_ctr2(nv_ctr_param->plat_nv_ctr->cookie,
img_desc, cert_nv_ctr);
return_if_error(rc);
}
/* Extract the parameters indicated in the image descriptor to
* authenticate the children images. */
if (img_desc->authenticated_data != NULL) {