diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/auth/auth_mod.c | 84 | ||||
-rw-r--r-- | drivers/auth/mbedtls/mbedtls_x509_parser.c | 8 | ||||
-rw-r--r-- | drivers/auth/tbbr/tbbr_cot.c | 75 |
3 files changed, 167 insertions, 0 deletions
diff --git a/drivers/auth/auth_mod.c b/drivers/auth/auth_mod.c index bdd3c5a1..41845561 100644 --- a/drivers/auth/auth_mod.c +++ b/drivers/auth/auth_mod.c @@ -40,6 +40,9 @@ #include <stdint.h> #include <string.h> +/* ASN.1 tags */ +#define ASN1_INTEGER 0x02 + #define return_if_error(rc) \ do { \ if (rc != 0) { \ @@ -227,6 +230,83 @@ static int auth_signature(const auth_method_param_sig_t *param, } /* + * Authenticate by Non-Volatile counter + * + * 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. + * + * Return: 0 = success, Otherwise = error + */ +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) +{ + char *p; + void *data_ptr = NULL; + unsigned int data_len, len, i; + unsigned int cert_nv_ctr, plat_nv_ctr; + int rc = 0; + + /* Get the counter value from current image. The AM expects the IPM + * to return the counter value as a DER encoded integer */ + rc = img_parser_get_auth_param(img_desc->img_type, param->cert_nv_ctr, + img, img_len, &data_ptr, &data_len); + return_if_error(rc); + + /* Parse the DER encoded integer */ + assert(data_ptr); + p = (char *)data_ptr; + if (*p != ASN1_INTEGER) { + /* Invalid ASN.1 integer */ + return 1; + } + p++; + + /* NV-counters are unsigned integers up to 32-bit */ + len = (unsigned int)(*p & 0x7f); + if ((*p & 0x80) || (len > 4)) { + return 1; + } + p++; + + /* Check the number is not negative */ + if (*p & 0x80) { + return 1; + } + + /* Convert to unsigned int. This code is for a little-endian CPU */ + cert_nv_ctr = 0; + for (i = 0; i < len; i++) { + 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) { + /* Invalid NV-counter */ + return 1; + } else if (cert_nv_ctr > plat_nv_ctr) { + if (img_desc->parent == NULL) { + /* This certificate has been signed with the ROT key. + * Update the platform counter value */ + rc = plat_set_nv_ctr(param->plat_nv_ctr->cookie, + cert_nv_ctr); + return_if_error(rc); + } else { + /* Secondary certificates cannot modify the counter */ + return 1; + } + } + + return 0; +} + +/* * Return the parent id in the output parameter '*parent_id' * * Return value: @@ -310,6 +390,10 @@ int auth_mod_verify_img(unsigned int img_id, rc = auth_signature(&auth_method->param.sig, img_desc, img_ptr, img_len); break; + case AUTH_METHOD_NV_CTR: + rc = auth_nvctr(&auth_method->param.nv_ctr, + img_desc, img_ptr, img_len); + break; default: /* Unknown authentication method */ rc = 1; diff --git a/drivers/auth/mbedtls/mbedtls_x509_parser.c b/drivers/auth/mbedtls/mbedtls_x509_parser.c index 52e69719..1a6a9a75 100644 --- a/drivers/auth/mbedtls/mbedtls_x509_parser.c +++ b/drivers/auth/mbedtls/mbedtls_x509_parser.c @@ -405,6 +405,13 @@ static int check_integrity(void *img, unsigned int img_len) /* * Extract an authentication parameter from an X509v3 certificate + * + * This function returns a pointer to the extracted data and its length. + * Depending on the type of parameter, a pointer to the data stored in the + * certificate may be returned (i.e. an octet string containing a hash). Other + * data may need to be copied and formatted (i.e. integers). In the later case, + * a buffer of the correct type needs to be statically allocated, filled and + * returned. */ static int get_auth_param(const auth_param_type_desc_t *type_desc, void *img, unsigned int img_len, @@ -422,6 +429,7 @@ static int get_auth_param(const auth_param_type_desc_t *type_desc, *param_len = (unsigned int)tbs.len; break; case AUTH_PARAM_HASH: + case AUTH_PARAM_NV_CTR: /* All these parameters are included as X509v3 extensions */ rc = get_ext(type_desc->cookie, param, param_len); break; diff --git a/drivers/auth/tbbr/tbbr_cot.c b/drivers/auth/tbbr/tbbr_cot.c index 6023c784..dae35d13 100644 --- a/drivers/auth/tbbr/tbbr_cot.c +++ b/drivers/auth/tbbr/tbbr_cot.c @@ -56,6 +56,11 @@ static unsigned char content_pk_buf[PK_DER_LEN]; /* * Parameter type descriptors */ +static auth_param_type_desc_t trusted_nv_ctr = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_NV_CTR, TRUSTED_FW_NVCOUNTER_OID); +static auth_param_type_desc_t non_trusted_nv_ctr = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_NV_CTR, NON_TRUSTED_FW_NVCOUNTER_OID); + static auth_param_type_desc_t subject_pk = AUTH_PARAM_TYPE_DESC( AUTH_PARAM_PUB_KEY, 0); static auth_param_type_desc_t sig = AUTH_PARAM_TYPE_DESC( @@ -116,6 +121,13 @@ static const auth_img_desc_t cot_desc[] = { .alg = &sig_alg, .data = &raw_data, } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } } }, .authenticated_data = { @@ -158,6 +170,13 @@ static const auth_img_desc_t cot_desc[] = { .alg = &sig_alg, .data = &raw_data, } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } } }, .authenticated_data = { @@ -193,6 +212,13 @@ static const auth_img_desc_t cot_desc[] = { .alg = &sig_alg, .data = &raw_data, } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } } }, .authenticated_data = { @@ -218,6 +244,13 @@ static const auth_img_desc_t cot_desc[] = { .alg = &sig_alg, .data = &raw_data, } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } } }, .authenticated_data = { @@ -260,6 +293,13 @@ static const auth_img_desc_t cot_desc[] = { .alg = &sig_alg, .data = &raw_data, } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } } }, .authenticated_data = { @@ -285,6 +325,13 @@ static const auth_img_desc_t cot_desc[] = { .alg = &sig_alg, .data = &raw_data, } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } } }, .authenticated_data = { @@ -327,6 +374,13 @@ static const auth_img_desc_t cot_desc[] = { .alg = &sig_alg, .data = &raw_data, } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } } }, .authenticated_data = { @@ -352,6 +406,13 @@ static const auth_img_desc_t cot_desc[] = { .alg = &sig_alg, .data = &raw_data, } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } } }, .authenticated_data = { @@ -394,6 +455,13 @@ static const auth_img_desc_t cot_desc[] = { .alg = &sig_alg, .data = &raw_data, } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &non_trusted_nv_ctr, + .plat_nv_ctr = &non_trusted_nv_ctr + } } }, .authenticated_data = { @@ -419,6 +487,13 @@ static const auth_img_desc_t cot_desc[] = { .alg = &sig_alg, .data = &raw_data, } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &non_trusted_nv_ctr, + .plat_nv_ctr = &non_trusted_nv_ctr + } } }, .authenticated_data = { |