summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorJuan Castillo <juan.castillo@arm.com>2016-01-22 11:05:57 +0000
committerJuan Castillo <juan.castillo@arm.com>2016-03-31 13:29:17 +0100
commit48279d52a7e339e88b5088ce5a276bf169c71754 (patch)
tree0230f81728e549206dfedfdb953d1415621d8da4 /drivers
parent96103d5af671b566cf523b0a5a1bb4fe4ef9bb64 (diff)
TBB: add non-volatile counter support
This patch adds support for non-volatile counter authentication to the Authentication Module. This method consists of matching the counter values provided in the certificates with the ones stored in the platform. If the value from the certificate is lower than the platform, the boot process is aborted. This mechanism protects the system against rollback. The TBBR CoT has been updated to include this method as part of the authentication process. Two counters are used: one for the trusted world images and another for the non trusted world images. ** NEW PLATFORM APIs (mandatory when TBB is enabled) ** int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr); This API returns the non-volatile counter value stored in the platform. The cookie in the first argument may be used to select the counter in case the platform provides more than one (i.e. TBSA compliant platforms must provide trusted and non-trusted counters). This cookie is specified in the CoT. int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr); This API sets a new counter value. The cookie may be used to select the counter to be updated. An implementation of these new APIs for ARM platforms is also provided. The values are obtained from the Trusted Non-Volatile Counters peripheral. The cookie is used to pass the extension OID. This OID may be interpreted by the platform to know which counter must return. On Juno, The trusted and non-trusted counter values have been tied to 31 and 223, respectively, and cannot be modified. ** IMPORTANT ** THIS PATCH BREAKS THE BUILD WHEN TRUSTED_BOARD_BOOT IS ENABLED. THE NEW PLATFORM APIs INTRODUCED IN THIS PATCH MUST BE IMPLEMENTED IN ORDER TO SUCCESSFULLY BUILD TF. Change-Id: Ic943b76b25f2a37f490eaaab6d87b4a8b3cbc89a
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 = {