Merge pull request #785 from dp-arm/dp/nvcounter
diff --git a/docs/porting-guide.md b/docs/porting-guide.md
index 67caa04..a74966c 100644
--- a/docs/porting-guide.md
+++ b/docs/porting-guide.md
@@ -702,12 +702,32 @@
 
 This function is mandatory when Trusted Board Boot is enabled. It sets a new
 counter value in the platform. The cookie in the first argument may be used to
-select the counter (as explained in plat_get_nv_ctr()).
+select the counter (as explained in plat_get_nv_ctr()). The second argument is
+the updated counter value to be written to the NV counter.
 
 The function returns 0 on success. Any other value means the counter value could
 not be updated.
 
 
+### Function: plat_set_nv_ctr2()
+
+    Argument : void *, const auth_img_desc_t *, unsigned int
+    Return   : int
+
+This function is optional when Trusted Board Boot is enabled. If this
+interface is defined, then `plat_set_nv_ctr()` need not be defined. The
+first argument passed is a cookie and is typically used to
+differentiate between a Non Trusted NV Counter and a Trusted NV
+Counter. The second argument is a pointer to an authentication image
+descriptor and may be used to decide if the counter is allowed to be
+updated or not. The third argument is the updated counter value to
+be written to the NV counter.
+
+The function returns 0 on success. Any other value means the counter value
+either could not be updated or the authentication image descriptor indicates
+that it is not allowed to be updated.
+
+
 2.3 Common mandatory function modifications
 ---------------------------------
 
diff --git a/drivers/auth/auth_mod.c b/drivers/auth/auth_mod.c
index 88ef0b0..2c8643f 100644
--- a/drivers/auth/auth_mod.c
+++ b/drivers/auth/auth_mod.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -50,6 +50,8 @@
 		} \
 	} while (0)
 
+#pragma weak plat_set_nv_ctr2
+
 /* Pointer to CoT */
 extern const auth_img_desc_t *const cot_desc_ptr;
 extern unsigned int auth_img_flags[];
@@ -297,21 +299,20 @@
 		/* 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;
-		}
+		rc = plat_set_nv_ctr2(param->plat_nv_ctr->cookie,
+			img_desc, cert_nv_ctr);
+		return_if_error(rc);
 	}
 
 	return 0;
 }
 
+int plat_set_nv_ctr2(void *cookie, const auth_img_desc_t *img_desc __unused,
+		unsigned int nv_ctr)
+{
+	return plat_set_nv_ctr(cookie, nv_ctr);
+}
+
 /*
  * Return the parent id in the output parameter '*parent_id'
  *
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index 5b4d11d..f904292 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -39,6 +39,7 @@
 /*******************************************************************************
  * Forward declarations
  ******************************************************************************/
+struct auth_img_desc_s;
 struct meminfo;
 struct image_info;
 struct entry_point_info;
@@ -274,6 +275,8 @@
 			unsigned int *flags);
 int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr);
 int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr);
+int plat_set_nv_ctr2(void *cookie, const struct auth_img_desc_s *img_desc,
+		unsigned int nv_ctr);
 
 #if LOAD_IMAGE_V2
 /*******************************************************************************
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index d0940b8..c2f28f9 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -167,9 +167,11 @@
 
     BL1_SOURCES		+=	${AUTH_SOURCES}					\
 				bl1/tbbr/tbbr_img_desc.c			\
-				plat/arm/common/arm_bl1_fwu.c
+				plat/arm/common/arm_bl1_fwu.c			\
+				plat/common/tbbr/plat_tbbr.c
 
-    BL2_SOURCES		+=	${AUTH_SOURCES}
+    BL2_SOURCES		+=	${AUTH_SOURCES}					\
+				plat/common/tbbr/plat_tbbr.c
 
     $(eval $(call FWU_FIP_ADD_IMG,NS_BL2U,--fwu))
 
diff --git a/plat/common/tbbr/plat_tbbr.c b/plat/common/tbbr/plat_tbbr.c
new file mode 100644
index 0000000..475564a
--- /dev/null
+++ b/plat/common/tbbr/plat_tbbr.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <auth/auth_mod.h>
+#include <platform.h>
+#include <platform_oid.h>
+#include <string.h>
+
+/*
+ * Store a new non-volatile counter value. This implementation
+ * only allows updating of the platform's Trusted NV counter when a
+ * certificate protected by the Trusted NV counter is signed with
+ * the ROT key. This avoids a compromised secondary certificate from
+ * updating the platform's Trusted NV counter, which could lead to the
+ * platform becoming unusable. The function is suitable for all TBBR
+ * compliant platforms.
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+int plat_set_nv_ctr2(void *cookie, const auth_img_desc_t *img_desc,
+		unsigned int nv_ctr)
+{
+	int trusted_nv_ctr;
+
+	assert(cookie != NULL);
+	assert(img_desc != NULL);
+
+	trusted_nv_ctr = strcmp(cookie, TRUSTED_FW_NVCOUNTER_OID) == 0;
+
+	/*
+	 * Only update the Trusted NV Counter if the certificate
+	 * has been signed with the ROT key. Non Trusted NV counter
+	 * updates are unconditional.
+	 */
+	if (!trusted_nv_ctr || (trusted_nv_ctr && img_desc->parent == NULL))
+		return plat_set_nv_ctr(cookie, nv_ctr);
+
+	/*
+	 * Trusted certificates not signed with the ROT key are not
+	 * allowed to update the Trusted NV Counter.
+	 */
+	return 1;
+}