summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/auth/auth_mod.c84
-rw-r--r--drivers/auth/mbedtls/mbedtls_x509_parser.c8
-rw-r--r--drivers/auth/tbbr/tbbr_cot.c75
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 = {