From f55886b7fae14a7a13c2a532224584de51d6ad84 Mon Sep 17 00:00:00 2001
From: Eduardo Barretto <ebarretto@linux.vnet.ibm.com>
Date: Thu, 8 Mar 2018 15:12:20 -0300
Subject: [PATCH 1/3] Fix Hardware Feature Object validation and tests

Monotonic Counters have read-only attributes. If during CreateObject the
supplied template specifies a value for any of the read-only attributes,
then the attempt should fail with the error code CKR_ATTRIBUTE_READ_ONLY.
Fixed tests that created Monotonic counters objects.

Signed-off-by: Eduardo Barretto <ebarretto@linux.vnet.ibm.com>
---
 testcases/misc_tests/obj_mgmt.c | 451 ++++++++++++++++++++--------------------
 testcases/pkcs11/hw_fn.c        | 413 ++++++++++++++++++------------------
 usr/lib/pkcs11/common/hwf_obj.c |   4 +-
 3 files changed, 444 insertions(+), 424 deletions(-)

diff --git a/testcases/misc_tests/obj_mgmt.c b/testcases/misc_tests/obj_mgmt.c
index 3ab0d03a..bc875c7c 100644
--- a/testcases/misc_tests/obj_mgmt.c
+++ b/testcases/misc_tests/obj_mgmt.c
@@ -1162,251 +1162,260 @@ CK_RV do_CreateTokenObjects(void)
 }
 
 /*
- * do_HW_Feature_Search Test:
+ * do_HWFeatureSearch Test:
  *
- * 1. Create 5 objects, 3 of which are HW_FEATURE objects.
+ * 1. Create 4 objects, 2 of which are HW_FEATURE objects (1 of them is a
+ *    monotonic counter).
  * 2. Search for objects using a template that does not have its
  *    HW_FEATURE attribute set.
  * 3. Result should be that the other 2 objects are returned, and
  *    not the HW_FEATURE objects.
  * 4. Search for objects using a template that does have its
  *    HW_FEATURE attribute set.
- * 5. Result should be that the 3 hardware feature objects are returned.
+ * 5. Result should be that the only hardware feature objects that is not a
+ *    monotonic counter should be returned.
  *
  */
-
 CK_RV do_HWFeatureSearch(void)
 {
-	unsigned int            i;
-	CK_RV 			rc, loc_rc;
-	CK_ULONG		find_count;
-	CK_SLOT_ID		slot_id;
-	CK_BBOOL		false = FALSE;
-	CK_BBOOL                true = TRUE;
-
-	CK_SESSION_HANDLE 	h_session;
-	CK_BYTE           	user_pin[PKCS11_MAX_PIN_LEN];
-	CK_ULONG          	user_pin_len;
-
-	/* A counter object */
-	CK_OBJECT_CLASS         counter1_class = CKO_HW_FEATURE;
-	CK_HW_FEATURE_TYPE      feature1_type = CKH_MONOTONIC_COUNTER;
-	CK_UTF8CHAR             counter1_label[] = "Monotonic counter";
-	CK_CHAR			counter1_value[16];
-	CK_ATTRIBUTE            counter1_template[] = {
-		{CKA_CLASS,		&counter1_class, sizeof(counter1_class)},
-		{CKA_HW_FEATURE_TYPE,	&feature1_type,  sizeof(feature1_type)},
-		{CKA_LABEL,		counter1_label,  sizeof(counter1_label)-1},
-		{CKA_VALUE,		counter1_value,	sizeof(counter1_value)},
-		{CKA_RESET_ON_INIT,	&true,		sizeof(true)},
-		{CKA_HAS_RESET,		&false,		sizeof(false)}
-	};
-	/* A clock object */
-	CK_OBJECT_CLASS         clock_class = CKO_HW_FEATURE;
-	CK_HW_FEATURE_TYPE      clock_type = CKH_CLOCK;
-	CK_UTF8CHAR             clock_label[] = "Clock";
-	CK_CHAR			clock_value[16];
-	CK_ATTRIBUTE            clock_template[] = {
-		{CKA_CLASS,		&clock_class, sizeof(clock_class)},
-		{CKA_HW_FEATURE_TYPE,	&clock_type,  sizeof(clock_type)},
-		{CKA_LABEL,		clock_label,  sizeof(clock_label)-1},
-		{CKA_VALUE,		clock_value,	sizeof(clock_value)}
-	};
-	/* A data object */
-	CK_OBJECT_CLASS		obj1_class = CKO_DATA;
-	CK_UTF8CHAR             obj1_label[] = "Object 1";
-	CK_BYTE			obj1_data[] = "Object 1's data";
-	CK_ATTRIBUTE            obj1_template[] = {
-		{CKA_CLASS,		&obj1_class,    sizeof(obj1_class)},
-		{CKA_TOKEN,		&true,          sizeof(true)},
-		{CKA_LABEL,		obj1_label,     sizeof(obj1_label)-1},
-		{CKA_VALUE,		obj1_data,	sizeof(obj1_data)}
-	};
-	/* A secret key object */
-	CK_OBJECT_CLASS		obj2_class = CKO_SECRET_KEY;
-	CK_KEY_TYPE		obj2_type = CKK_AES;
-	CK_UTF8CHAR             obj2_label[] = "Object 2";
-	CK_BYTE			obj2_data[AES_KEY_SIZE_128];
-	CK_ATTRIBUTE            obj2_template[] = {
-		{CKA_CLASS,		&obj2_class,    sizeof(obj2_class)},
-		{CKA_TOKEN,		&true,          sizeof(true)},
-		{CKA_KEY_TYPE,		&obj2_type,	sizeof(obj2_type)},
-		{CKA_LABEL,		obj2_label,     sizeof(obj2_label)-1},
-		{CKA_VALUE,		obj2_data,	sizeof(obj2_data)}
-	};
-
-	CK_OBJECT_HANDLE        h_counter1,
-				h_clock,
-				h_obj1,
-				h_obj2,
-				obj_list[10];
-	CK_ATTRIBUTE		find_tmpl[] = {
-		{CKA_CLASS,	&counter1_class, sizeof(counter1_class)}
+    unsigned int    i;
+    CK_RV           rc, loc_rc;
+    CK_ULONG        find_count;
+    CK_SLOT_ID      slot_id;
+    CK_BBOOL        false = FALSE;
+    CK_BBOOL        true = TRUE;
+
+    CK_SESSION_HANDLE   h_session;
+    CK_BYTE             user_pin[PKCS11_MAX_PIN_LEN];
+    CK_ULONG            user_pin_len;
+
+    /* A counter object */
+    CK_OBJECT_CLASS     counter1_class = CKO_HW_FEATURE;
+    CK_HW_FEATURE_TYPE  feature1_type = CKH_MONOTONIC_COUNTER;
+    CK_UTF8CHAR         counter1_label[] = "Monotonic counter";
+    CK_CHAR             counter1_value[16];
+    CK_ATTRIBUTE        counter1_template[] = {
+        {CKA_CLASS,             &counter1_class,    sizeof(counter1_class)},
+        {CKA_HW_FEATURE_TYPE,   &feature1_type,     sizeof(feature1_type)},
+        {CKA_LABEL,             counter1_label,     sizeof(counter1_label)-1},
+        {CKA_VALUE,             counter1_value,     sizeof(counter1_value)},
+        {CKA_RESET_ON_INIT,     &true,              sizeof(true)},
+        {CKA_HAS_RESET,         &false,             sizeof(false)}
+    };
+
+    /* A clock object */
+    CK_OBJECT_CLASS     clock_class = CKO_HW_FEATURE;
+    CK_HW_FEATURE_TYPE  clock_type = CKH_CLOCK;
+    CK_UTF8CHAR         clock_label[] = "Clock";
+    CK_CHAR             clock_value[16];
+    CK_ATTRIBUTE        clock_template[] = {
+        {CKA_CLASS,             &clock_class,   sizeof(clock_class)},
+        {CKA_HW_FEATURE_TYPE,   &clock_type,    sizeof(clock_type)},
+        {CKA_LABEL,             clock_label,    sizeof(clock_label)-1},
+        {CKA_VALUE,             clock_value,    sizeof(clock_value)}
+    };
+
+    /* A data object */
+    CK_OBJECT_CLASS obj1_class = CKO_DATA;
+    CK_UTF8CHAR     obj1_label[] = "Object 1";
+    CK_BYTE         obj1_data[] = "Object 1's data";
+    CK_ATTRIBUTE    obj1_template[] = {
+        {CKA_CLASS, &obj1_class,    sizeof(obj1_class)},
+        {CKA_TOKEN, &true,          sizeof(true)},
+        {CKA_LABEL, obj1_label,     sizeof(obj1_label)-1},
+        {CKA_VALUE, obj1_data,      sizeof(obj1_data)}
+    };
+
+    /* A secret key object */
+    CK_OBJECT_CLASS obj2_class = CKO_SECRET_KEY;
+    CK_KEY_TYPE     obj2_type = CKK_AES;
+    CK_UTF8CHAR     obj2_label[] = "Object 2";
+    CK_BYTE         obj2_data[AES_KEY_SIZE_128];
+    CK_ATTRIBUTE    obj2_template[] = {
+		{CKA_CLASS,     &obj2_class,    sizeof(obj2_class)},
+		{CKA_TOKEN,     &true,          sizeof(true)},
+		{CKA_KEY_TYPE,  &obj2_type,     sizeof(obj2_type)},
+		{CKA_LABEL,     obj2_label,     sizeof(obj2_label)-1},
+		{CKA_VALUE,     obj2_data,      sizeof(obj2_data)}
 	};
 
-        if (skip_token_obj == TRUE) {
-                testcase_notice("Skipping tests that creates token objects");
-                return CKR_OK;
+    CK_OBJECT_HANDLE h_counter1,
+                     h_clock,
+                     h_obj1,
+                     h_obj2,
+                     obj_list[10];
+
+    CK_ATTRIBUTE find_tmpl[] = {
+        {CKA_CLASS,	&counter1_class, sizeof(counter1_class)}
+    };
+
+    if (skip_token_obj == TRUE) {
+        testcase_notice("Skipping tests that creates token objects");
+        return CKR_OK;
+    }
+
+    slot_id = SLOT_ID;
+
+    testcase_begin("starting...");
+
+    if (get_user_pin(user_pin))
+        return CKR_FUNCTION_FAILED;
+
+    user_pin_len = (CK_ULONG)strlen((char *)user_pin);
+
+    /* Open a session with the token */
+    rc = funcs->C_OpenSession(slot_id,
+                              (CKF_SERIAL_SESSION|CKF_RW_SESSION),
+                              NULL_PTR,
+                              NULL_PTR,
+                              &h_session);
+    if (rc != CKR_OK) {
+        testcase_fail("C_OpenSession() rc = %s", p11_get_ckr(rc));
+        goto done;
+    }
+
+    // Login correctly
+    rc = funcs->C_Login(h_session, CKU_USER, user_pin, user_pin_len);
+    if (rc != CKR_OK) {
+        testcase_fail("C_Login() rc = %s", p11_get_ckr(rc));
+        goto session_close;
+    }
+
+    /* Create the 4 test objects */
+    rc = funcs->C_CreateObject(h_session, obj1_template, 4, &h_obj1);
+    if (rc != CKR_OK) {
+        testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc));
+		return rc;
+	}
+
+    rc = funcs->C_CreateObject(h_session, obj2_template, 5, &h_obj2);
+    if (rc != CKR_OK) {
+        testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc));
+        goto destroy_1;
+    }
+
+    /* try and create a monotonic object. This should fail
+     * since it is a read only feature.
+     */
+    rc = funcs->C_CreateObject(h_session, counter1_template, 6, &h_counter1);
+    if (rc != CKR_ATTRIBUTE_READ_ONLY) {
+        testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc));
+        goto destroy_2;
+    }
+
+    rc = funcs->C_CreateObject(h_session, clock_template, 4, &h_clock);
+    if (rc != CKR_OK) {
+        testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc));
+        goto destroy_2;
+    }
+
+
+    /* Search for the 2 objects w/o HW_FEATURE set */
+    /* A NULL template here should return all objects in v2.01, but
+     * in v2.11, it should return all objects *except* HW_FEATURE
+     * objects.
+     */
+    rc = funcs->C_FindObjectsInit(h_session, NULL, 0);
+    if (rc != CKR_OK) {
+        testcase_fail("C_FindObjectsInit() rc = %s", p11_get_ckr(rc));
+        goto destroy;
+    }
+
+    rc = funcs->C_FindObjects(h_session, obj_list, 10, &find_count);
+    if (rc != CKR_OK) {
+        testcase_fail("C_FindObjects() rc = %s", p11_get_ckr(rc));
+        goto destroy;
+    }
+
+    /* So, we created 4 objects before here, and then searched with a NULL
+     * template, so that should return all objects except our hardware
+     * feature object
+     */
+    if (find_count != 2) {
+        testcase_fail("found %ld objects when expected 2", find_count);
+        rc = -1;
+        goto destroy;
+    }
+
+    if (obj_list[0] != h_obj1 && obj_list[0] != h_obj2) {
+        testcase_fail("found the wrong object handle");
+        rc = -1;
+        goto destroy;
+    }
+
+    if (obj_list[1] != h_obj1 && obj_list[1] != h_obj2) {
+        testcase_fail("found the wrong object handle");
+        rc = -1;
+        goto destroy;
+    }
+
+    rc = funcs->C_FindObjectsFinal(h_session);
+    if (rc != CKR_OK) {
+        testcase_fail("C_FindObjectsFinal() rc = %s", p11_get_ckr(rc));
+        goto destroy;
+    }
+
+    // Now find the hardware feature objects
+    rc = funcs->C_FindObjectsInit(h_session, find_tmpl, 1);
+    if (rc != CKR_OK) {
+        testcase_fail("C_FindObjectsInit() rc = %s", p11_get_ckr(rc));
+        goto destroy;
+    }
+
+    rc = funcs->C_FindObjects(h_session, obj_list, 10, &find_count);
+    if (rc != CKR_OK) {
+        testcase_fail("C_FindObjects() rc = %s", p11_get_ckr(rc));
+        goto destroy;
+    }
+
+    if (find_count != 1) {
+        testcase_fail("found %ld objects when expected 1", find_count);
+        funcs->C_FindObjectsFinal(h_session);
+        rc = -1;
+        goto destroy;
+    }
+
+    /* Make sure we got the right ones */
+	for (i=0; i < find_count; i++) {
+        if (obj_list[i] != h_counter1 && obj_list[i] != h_clock) {
+            testcase_fail("found the wrong object handles");
+            rc = -1;
         }
+    }
 
-	slot_id = SLOT_ID;
-
-        testcase_begin("starting...");
-
-	if (get_user_pin(user_pin))
-		return CKR_FUNCTION_FAILED;
-	user_pin_len = (CK_ULONG)strlen((char *)user_pin);
-
-	/* Open a session with the token */
-	if( (rc = funcs->C_OpenSession(slot_id,
-					(CKF_SERIAL_SESSION|CKF_RW_SESSION),
-					NULL_PTR,
-					NULL_PTR,
-					&h_session)) != CKR_OK ) {
-                testcase_fail("C_OpenSession() rc = %s", p11_get_ckr(rc));
-		goto done;
-	}
-
-	// Login correctly
-	rc = funcs->C_Login(h_session, CKU_USER, user_pin, user_pin_len);
-	if( rc != CKR_OK ) {
-                testcase_fail("C_Login() rc = %s", p11_get_ckr(rc));
-		goto session_close;
-	}
-
-	/* Create the 3 test objects */
-	if( (rc = funcs->C_CreateObject(h_session, obj1_template, 4, &h_obj1)) != CKR_OK) {
-                testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc));
-		return rc;
-	}
-
-	if( (rc = funcs->C_CreateObject(h_session, obj2_template, 5, &h_obj2)) != CKR_OK) {
-                testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc));
-		goto destroy_1;
-	}
-
-	/* try and create a monotonic object. This should fail
-	 * since it is a read only feature.
-	 */
-	if( (rc = funcs->C_CreateObject(h_session, counter1_template, 6, &h_counter1)) != CKR_ATTRIBUTE_READ_ONLY) {
-                testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc));
-		goto destroy_2;
-	}
-
-	if( (rc = funcs->C_CreateObject(h_session, clock_template, 4, &h_clock)) != CKR_OK) {
-                testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc));
-		goto destroy_2;
-	}
-
-
-	/* Search for the 2 objects w/o HW_FEATURE set */
-
-	/* A NULL template here should return all objects in v2.01, but
-	 * in v2.11, it should return all objects *except* HW_FEATURE
-	 * objects. - KEY
-	 */
-	rc = funcs->C_FindObjectsInit(h_session, NULL, 0 );
-	if (rc != CKR_OK) {
-                testcase_fail("C_FindObjectsInit() rc = %s", p11_get_ckr(rc));
-		goto destroy;
-	}
-
-	rc = funcs->C_FindObjects(h_session, obj_list, 10, &find_count );
-	if (rc != CKR_OK) {
-                testcase_fail("C_FindObjects() rc = %s", p11_get_ckr(rc));
-		goto destroy;
-	}
-
-	/* So, we created 3 objects before here, and then searched with a NULL
-	 * template, so that should return all objects except our hardware
-	 * feature object. -KEY */
-	if (find_count != 2) {
-                testcase_fail("found %ld objects when expected 2", find_count);
-		rc = -1;
-		goto destroy;
-	}
-
-	if (obj_list[0] != h_obj1 && obj_list[0] != h_obj2) {
-                testcase_fail("found the wrong object handle");
-		rc = -1;
-		goto destroy;
-	}
-
-	if (obj_list[1] != h_obj1 && obj_list[1] != h_obj2) {
-                testcase_fail("found the wrong object handle");
-		rc = -1;
-		goto destroy;
-	}
-
-	rc = funcs->C_FindObjectsFinal(h_session);
-	if (rc != CKR_OK) {
-                testcase_fail("C_FindObjectsFinal() rc = %s", p11_get_ckr(rc));
-		goto destroy;
-	}
-
-
-	// Now find the hardware feature objects
-	rc = funcs->C_FindObjectsInit(h_session, find_tmpl, 1 );
-	if (rc != CKR_OK) {
-                testcase_fail("C_FindObjectsInit() rc = %s", p11_get_ckr(rc));
-		goto destroy;
-	}
+    rc = funcs->C_FindObjectsFinal(h_session);
+    if (rc != CKR_OK) {
+        testcase_fail("C_FindObjectsFinal() rc = %s", p11_get_ckr(rc));
+    }
 
-	rc = funcs->C_FindObjects(h_session, obj_list, 10, &find_count );
-	if (rc != CKR_OK) {
-                testcase_fail("C_FindObjects() rc = %s", p11_get_ckr(rc));
-		goto destroy;
-	}
-
-	if (find_count != 1) {
-                testcase_fail("found %ld objects when expected 1", find_count);
-		funcs->C_FindObjectsFinal(h_session);   // TODO: check if we really need this here
-		rc = -1;
-		goto destroy;
-	}
-
-	/* Make sure we got the right ones */
-	for( i=0; i < find_count; i++) {
-		if(obj_list[i] != h_counter1 &&
-		   obj_list[i] != h_clock)
-		{
-
-                        testcase_fail("found the wrong object handles");
-			rc = -1;
-		}
-	}
-
-	rc = funcs->C_FindObjectsFinal(h_session );
-	if (rc != CKR_OK) {
-                testcase_fail("C_FindObjectsFinal() rc = %s", p11_get_ckr(rc));
-	}
-
-        testcase_pass("Looks okay...");
+    testcase_pass("Looks okay...");
 
 destroy:
-	/* Destroy the created objects, don't clobber the rc */
-	loc_rc = funcs->C_DestroyObject(h_session, h_clock);
-	if( loc_rc != CKR_OK )
-                testcase_fail("C_DestroyObject() rc = %s", p11_get_ckr(loc_rc));
+    /* Destroy the created objects, don't clobber the rc */
+    loc_rc = funcs->C_DestroyObject(h_session, h_clock);
+    if (loc_rc != CKR_OK)
+        testcase_fail("C_DestroyObject() rc = %s", p11_get_ckr(loc_rc));
 destroy_2:
-	loc_rc = funcs->C_DestroyObject(h_session, h_obj2);
-	if( loc_rc != CKR_OK )
-                testcase_fail("C_DestroyObject() rc = %s", p11_get_ckr(loc_rc));
+    loc_rc = funcs->C_DestroyObject(h_session, h_obj2);
+    if (loc_rc != CKR_OK)
+        testcase_fail("C_DestroyObject() rc = %s", p11_get_ckr(loc_rc));
 destroy_1:
-	loc_rc = funcs->C_DestroyObject(h_session, h_obj1);
-	if( loc_rc != CKR_OK )
-                testcase_fail("C_DestroyObject() rc = %s", p11_get_ckr(loc_rc));
+    loc_rc = funcs->C_DestroyObject(h_session, h_obj1);
+    if (loc_rc != CKR_OK)
+        testcase_fail("C_DestroyObject() rc = %s", p11_get_ckr(loc_rc));
 
-	loc_rc = funcs->C_Logout(h_session);
-	if( loc_rc != CKR_OK )
-                testcase_fail("C_Logout() rc = %s", p11_get_ckr(loc_rc));
+    loc_rc = funcs->C_Logout(h_session);
+    if (loc_rc != CKR_OK)
+        testcase_fail("C_Logout() rc = %s", p11_get_ckr(loc_rc));
 
 session_close:
-	/* Close the session */
-	if( (loc_rc = funcs->C_CloseSession(h_session)) != CKR_OK )
-                testcase_fail("C_CloseSession() rc = %s", p11_get_ckr(loc_rc));
+    /* Close the session */
+    loc_rc = funcs->C_CloseSession(h_session);
+    if (loc_rc != CKR_OK)
+        testcase_fail("C_CloseSession() rc = %s", p11_get_ckr(loc_rc));
+
 done:
-	return rc;
+    return rc;
 }
 
 CK_RV obj_mgmt_functions()
diff --git a/testcases/pkcs11/hw_fn.c b/testcases/pkcs11/hw_fn.c
index 701a6770..62632291 100644
--- a/testcases/pkcs11/hw_fn.c
+++ b/testcases/pkcs11/hw_fn.c
@@ -40,227 +40,238 @@ CK_SESSION_HANDLE	sess;
 /*
  * do_HW_Feature_Seatch Test:
  *
- * 1. Create 5 objects, 3 of which are HW_FEATURE objects.
+ * 1. Create 5 objects, 3 of which are HW_FEATURE objects (2 of them are
+ *    monotonic counters).
  * 2. Search for objects using a template that does not have its
  *    HW_FEATURE attribute set.
  * 3. Result should be that the other 2 objects are returned, and
  *    not the HW_FEATURE objects.
  * 4. Search for objects using a template that does have its
  *    HW_FEATURE attribute set.
- * 5. Result should be that the 3 hardware feature objects are returned.
+ * 5. Result should be that the only hardware feature objects that are not
+ *    monotonic counters should be returned.
  *
  */
-
 int do_HW_Feature_Search(void)
 {
-	unsigned int            i;
-	CK_RV 			rc;
-	CK_ULONG		find_count;
-
-	CK_BBOOL		false = FALSE;
-        CK_BBOOL                true = TRUE;
-
-	// A counter object
-        CK_OBJECT_CLASS         counter1_class = CKO_HW_FEATURE;
-        CK_HW_FEATURE_TYPE      feature1_type = CKH_MONOTONIC_COUNTER;
-        CK_UTF8CHAR             counter1_label[] = "Monotonic counter";
-	CK_CHAR			counter1_value[16];
-        CK_ATTRIBUTE            counter1_template[] = {
-                {CKA_CLASS,		&counter1_class, sizeof(counter1_class)},
-                {CKA_HW_FEATURE_TYPE,	&feature1_type,  sizeof(feature1_type)},
-                {CKA_LABEL,		counter1_label,  sizeof(counter1_label)-1},
-		{CKA_VALUE,		counter1_value,	sizeof(counter1_value)},
-		{CKA_RESET_ON_INIT,	&true,		sizeof(true)},
-		{CKA_HAS_RESET,		&false,		sizeof(false)}
-        };
-	// Another counter object
-        CK_OBJECT_CLASS         counter2_class = CKO_HW_FEATURE;
-        CK_HW_FEATURE_TYPE      feature2_type = CKH_MONOTONIC_COUNTER;
-        CK_UTF8CHAR             counter2_label[] = "Monotonic counter";
-	CK_CHAR			counter2_value[16];
-        CK_ATTRIBUTE            counter2_template[] = {
-                {CKA_CLASS,		&counter2_class, sizeof(counter2_class)},
-                {CKA_HW_FEATURE_TYPE,	&feature2_type,  sizeof(feature2_type)},
-                {CKA_LABEL,		counter2_label,  sizeof(counter2_label)-1},
-		{CKA_VALUE,		counter2_value,	sizeof(counter2_value)},
-		{CKA_RESET_ON_INIT,	&true,		sizeof(true)},
-		{CKA_HAS_RESET,		&false,		sizeof(false)}
-        };
-	// A clock object
-        CK_OBJECT_CLASS         clock_class = CKO_HW_FEATURE;
-        CK_HW_FEATURE_TYPE      clock_type = CKH_CLOCK;
-        CK_UTF8CHAR             clock_label[] = "Clock";
-	CK_CHAR			clock_value[16];
-        CK_ATTRIBUTE            clock_template[] = {
-                {CKA_CLASS,		&clock_class, sizeof(clock_class)},
-                {CKA_HW_FEATURE_TYPE,	&clock_type,  sizeof(clock_type)},
-                {CKA_LABEL,		clock_label,  sizeof(clock_label)-1},
-		{CKA_VALUE,		clock_value,	sizeof(clock_value)}
-        };
-	// A data object
-	CK_OBJECT_CLASS		obj1_class = CKO_DATA;
-        CK_UTF8CHAR             obj1_label[] = "Object 1";
-	CK_BYTE			obj1_data[] = "Object 1's data";
-        CK_ATTRIBUTE            obj1_template[] = {
-                {CKA_CLASS,		&obj1_class,    sizeof(obj1_class)},
-                {CKA_TOKEN,		&true,          sizeof(true)},
-                {CKA_LABEL,		obj1_label,     sizeof(obj1_label)-1},
-		{CKA_VALUE,		obj1_data,	sizeof(obj1_data)}
-        };
-	// A secret key object
-	CK_OBJECT_CLASS		obj2_class = CKO_SECRET_KEY;
-	CK_KEY_TYPE		obj2_type = CKK_AES;
-        CK_UTF8CHAR             obj2_label[] = "Object 2";
-	CK_BYTE			obj2_data[AES_KEY_SIZE_128];
-        CK_ATTRIBUTE            obj2_template[] = {
-                {CKA_CLASS,		&obj2_class,    sizeof(obj2_class)},
-                {CKA_TOKEN,		&true,          sizeof(true)},
-		{CKA_KEY_TYPE,		&obj2_type,	sizeof(obj2_type)},
-                {CKA_LABEL,		obj2_label,     sizeof(obj2_label)-1},
-		{CKA_VALUE,		obj2_data,	sizeof(obj2_data)}
-        };
-
-        CK_OBJECT_HANDLE        h_counter1,
-				h_counter2,
-				h_clock,
-				h_obj1,
-				h_obj2,
-				obj_list[10];
-	CK_ATTRIBUTE		find_tmpl[] = {
-		{CKA_CLASS,	&counter1_class, sizeof(counter1_class)}
-	};
-
-
-	/* Create the 3 test objects */
-	if( (rc = funcs->C_CreateObject(sess, obj1_template, 4, &h_obj1)) != CKR_OK) {
-		show_error("C_CreateObject #1", rc);
-		return rc;
-	}
-
-	if( (rc = funcs->C_CreateObject(sess, obj2_template, 5, &h_obj2)) != CKR_OK) {
-		show_error("C_CreateObject #2", rc);
-		goto destroy_1;
-	}
-
-	if( (rc = funcs->C_CreateObject(sess, counter1_template, 6, &h_counter1)) != CKR_OK) {
-		show_error("C_CreateObject #3", rc);
-		goto destroy_2;
-	}
-
-	if( (rc = funcs->C_CreateObject(sess, counter2_template, 6, &h_counter2)) != CKR_OK) {
-		show_error("C_CreateObject #4", rc);
-		goto destroy_3;
-	}
-
-	if( (rc = funcs->C_CreateObject(sess, clock_template, 4, &h_clock)) != CKR_OK) {
-		show_error("C_CreateObject #5", rc);
-		goto destroy_4;
-	}
-
-
-	// Search for the 2 objects w/o HW_FEATURE set
-	//
-
-	// A NULL template here should return all objects in v2.01, but
-	// in v2.11, it should return all objects *except* HW_FEATURE
-	// objects. - KEY
-	rc = funcs->C_FindObjectsInit( sess, NULL, 0 );
-	if (rc != CKR_OK) {
-		show_error("   C_FindObjectsInit #1", rc );
-		goto done;
-	}
-
-	rc = funcs->C_FindObjects( sess, obj_list, 10, &find_count );
-	if (rc != CKR_OK) {
-		show_error("   C_FindObjects #1", rc );
-		goto done;
-	}
-
-	/* So, we created 3 objects before here, and then searched with a NULL
-	 * template, so that should return all objects except our hardware
-	 * feature object. -KEY */
-	if (find_count != 2) {
-		printf("%s:%d ERROR:  C_FindObjects #1 should have found 2 objects!\n"
-				"           It found %ld objects\n", __FILE__, __LINE__,
-				find_count);
-		rc = -1;
-		goto done;
-	}
-
-	if (obj_list[0] != h_obj1 && obj_list[0] != h_obj2) {
-		printf("%s:%d ERROR:  C_FindObjects #1 found the wrong objects!\n",
-				__FILE__, __LINE__);
-		rc = -1;
-		goto done;
-	}
-
-	if (obj_list[1] != h_obj1 && obj_list[1] != h_obj2) {
-		printf("%s:%d ERROR:  C_FindObjects #1 found the wrong objects!\n",
-				__FILE__, __LINE__);
-		rc = -1;
-		goto done;
-	}
-
-	rc = funcs->C_FindObjectsFinal( sess );
-	if (rc != CKR_OK) {
-		show_error("   C_FindObjectsFinal #1", rc );
-		goto done;
-	}
-
+    unsigned int    i;
+    CK_RV 			rc;
+    CK_ULONG		find_count;
+
+    CK_BBOOL        false = FALSE;
+    CK_BBOOL        true = TRUE;
+
+    // A counter object
+    CK_OBJECT_CLASS         counter1_class = CKO_HW_FEATURE;
+    CK_HW_FEATURE_TYPE      feature1_type = CKH_MONOTONIC_COUNTER;
+    CK_UTF8CHAR             counter1_label[] = "Monotonic counter";
+    CK_CHAR                 counter1_value[16];
+    CK_ATTRIBUTE            counter1_template[] = {
+        {CKA_CLASS,             &counter1_class,    sizeof(counter1_class)},
+        {CKA_HW_FEATURE_TYPE,   &feature1_type,     sizeof(feature1_type)},
+        {CKA_LABEL,             counter1_label,     sizeof(counter1_label)-1},
+        {CKA_VALUE,             counter1_value,     sizeof(counter1_value)},
+        {CKA_RESET_ON_INIT,     &true,              sizeof(true)},
+        {CKA_HAS_RESET,         &false,             sizeof(false)}
+    };
+
+    // Another counter object
+    CK_OBJECT_CLASS         counter2_class = CKO_HW_FEATURE;
+    CK_HW_FEATURE_TYPE      feature2_type = CKH_MONOTONIC_COUNTER;
+    CK_UTF8CHAR             counter2_label[] = "Monotonic counter";
+    CK_CHAR                 counter2_value[16];
+    CK_ATTRIBUTE            counter2_template[] = {
+        {CKA_CLASS,             &counter2_class,    sizeof(counter2_class)},
+        {CKA_HW_FEATURE_TYPE,   &feature2_type,     sizeof(feature2_type)},
+        {CKA_LABEL,             counter2_label,     sizeof(counter2_label)-1},
+        {CKA_VALUE,             counter2_value,     sizeof(counter2_value)},
+        {CKA_RESET_ON_INIT,     &true,              sizeof(true)},
+        {CKA_HAS_RESET,         &false,             sizeof(false)}
+    };
+
+    // A clock object
+    CK_OBJECT_CLASS         clock_class = CKO_HW_FEATURE;
+    CK_HW_FEATURE_TYPE      clock_type = CKH_CLOCK;
+    CK_UTF8CHAR             clock_label[] = "Clock";
+    CK_CHAR                 clock_value[16];
+    CK_ATTRIBUTE            clock_template[] = {
+        {CKA_CLASS,             &clock_class,   sizeof(clock_class)},
+        {CKA_HW_FEATURE_TYPE,   &clock_type,    sizeof(clock_type)},
+        {CKA_LABEL,             clock_label,    sizeof(clock_label)-1},
+        {CKA_VALUE,             clock_value,    sizeof(clock_value)}
+    };
+
+    // A data object
+    CK_OBJECT_CLASS     obj1_class = CKO_DATA;
+    CK_UTF8CHAR         obj1_label[] = "Object 1";
+    CK_BYTE             obj1_data[] = "Object 1's data";
+    CK_ATTRIBUTE        obj1_template[] = {
+        {CKA_CLASS,     &obj1_class,    sizeof(obj1_class)},
+        {CKA_TOKEN,     &true,          sizeof(true)},
+        {CKA_LABEL,     obj1_label,     sizeof(obj1_label)-1},
+        {CKA_VALUE,     obj1_data,      sizeof(obj1_data)}
+    };
 
-	// Now find the hardware feature objects
-        rc = funcs->C_FindObjectsInit( sess, find_tmpl, 1 );
-        if (rc != CKR_OK) {
-                show_error("   C_FindObjectsInit #2", rc );
-                goto done;
-        }
-
-        rc = funcs->C_FindObjects( sess, obj_list, 10, &find_count );
-        if (rc != CKR_OK) {
-                show_error("   C_FindObjects #2", rc );
-                goto done;
-        }
-
-        if (find_count != 3) {
-                printf("%s:%d ERROR:  C_FindObjects #2 should have found 3 objects!\n"
-                       "           It found %ld objects\n", __FILE__, __LINE__,
-		       find_count);
-                funcs->C_FindObjectsFinal( sess );
-		rc = -1;
-                goto done;
-        }
-
-	/* Make sure we got the right ones */
-	for( i=0; i < find_count; i++) {
-		if(	obj_list[i] != h_counter1 &&
-			obj_list[i] != h_counter2 &&
-			obj_list[i] != h_clock)
-		{
-
-			printf("%s:%d ERROR:  C_FindObjects #2 found the wrong\n"
-					" objects!", __FILE__, __LINE__);
-			rc = -1;
-		}
+	// A secret key object
+    CK_OBJECT_CLASS     obj2_class = CKO_SECRET_KEY;
+    CK_KEY_TYPE         obj2_type = CKK_AES;
+    CK_UTF8CHAR         obj2_label[] = "Object 2";
+    CK_BYTE             obj2_data[AES_KEY_SIZE_128];
+    CK_ATTRIBUTE        obj2_template[] = {
+        {CKA_CLASS,     &obj2_class,    sizeof(obj2_class)},
+        {CKA_TOKEN,     &true,          sizeof(true)},
+        {CKA_KEY_TYPE,  &obj2_type,     sizeof(obj2_type)},
+        {CKA_LABEL,     obj2_label,     sizeof(obj2_label)-1},
+        {CKA_VALUE,     obj2_data,      sizeof(obj2_data)}
+    };
+
+    CK_OBJECT_HANDLE h_counter1,
+                     h_counter2,
+                     h_clock,
+                     h_obj1,
+                     h_obj2,
+                     obj_list[10];
+
+    CK_ATTRIBUTE find_tmpl[] = {
+        {CKA_CLASS,	&counter1_class, sizeof(counter1_class)}
+    };
+
+    /* Create the 5 test objects */
+    rc = funcs->C_CreateObject(sess, obj1_template, 4, &h_obj1);
+    if (rc != CKR_OK) {
+        show_error("C_CreateObject #1", rc);
+        return rc;
+    }
+
+    rc = funcs->C_CreateObject(sess, obj2_template, 5, &h_obj2);
+    if (rc != CKR_OK) {
+        show_error("C_CreateObject #2", rc);
+        goto destroy_1;
+    }
+
+    rc = funcs->C_CreateObject(sess, counter1_template, 6, &h_counter1);
+    if (rc != CKR_ATTRIBUTE_READ_ONLY) {
+        show_error("C_CreateObject #3", rc);
+        goto destroy_2;
+    }
+
+    rc = funcs->C_CreateObject(sess, counter2_template, 6, &h_counter2);
+    if (rc != CKR_ATTRIBUTE_READ_ONLY) {
+        show_error("C_CreateObject #4", rc);
+        goto destroy_3;
+    }
+
+    rc = funcs->C_CreateObject(sess, clock_template, 4, &h_clock);
+    if (rc != CKR_OK) {
+        show_error("C_CreateObject #5", rc);
+        goto destroy_4;
+    }
+
+
+    /* Search for the 2 objects w/o HW_FEATURE set
+     * A NULL template here should return all objects in v2.01, but
+     * in v2.11, it should return all objects *except* HW_FEATURE
+     * objects.
+     */
+    rc = funcs->C_FindObjectsInit(sess, NULL, 0);
+    if (rc != CKR_OK) {
+        show_error("   C_FindObjectsInit #1", rc);
+        goto done;
+    }
+
+    rc = funcs->C_FindObjects(sess, obj_list, 10, &find_count);
+    if (rc != CKR_OK) {
+        show_error("   C_FindObjects #1", rc);
+        goto done;
+    }
+
+    /* So, we created 5 objects before here, and then searched with a NULL
+     * template, so that should return all objects except our hardware
+     * feature object.
+     */
+    if (find_count != 2) {
+        printf("%s:%d ERROR:  C_FindObjects #1 should have found 2 objects!\n"
+               "           It found %ld objects\n", __FILE__, __LINE__,
+               find_count);
+        rc = -1;
+        goto done;
+    }
+
+    if (obj_list[0] != h_obj1 && obj_list[0] != h_obj2) {
+        printf("%s:%d ERROR:  C_FindObjects #1 found the wrong objects!\n",
+                __FILE__, __LINE__);
+        rc = -1;
+        goto done;
+    }
+
+    if (obj_list[1] != h_obj1 && obj_list[1] != h_obj2) {
+        printf("%s:%d ERROR:  C_FindObjects #1 found the wrong objects!\n",
+                __FILE__, __LINE__);
+        rc = -1;
+        goto done;
+    }
+
+    rc = funcs->C_FindObjectsFinal(sess);
+    if (rc != CKR_OK) {
+        show_error("   C_FindObjectsFinal #1", rc);
+        goto done;
+    }
+
+
+    /* Now find the hardware feature objects (should find only 1 since monotonic
+     * counters are read-only
+     */
+    rc = funcs->C_FindObjectsInit(sess, find_tmpl, 1);
+    if (rc != CKR_OK) {
+        show_error("   C_FindObjectsInit #2", rc);
+        goto done;
+    }
+
+    rc = funcs->C_FindObjects(sess, obj_list, 10, &find_count);
+    if (rc != CKR_OK) {
+        show_error("   C_FindObjects #2", rc);
+        goto done;
+    }
+
+    if (find_count != 1) {
+        printf("%s:%d ERROR:  C_FindObjects #2 should have found 1 object!\n"
+               "           It found %ld objects\n", __FILE__, __LINE__,
+               find_count);
+        funcs->C_FindObjectsFinal(sess);
+        rc = -1;
+        goto done;
+    }
+
+    /* Make sure we got the right ones */
+    for( i=0; i < find_count; i++) {
+        if (obj_list[i] != h_counter1 &&
+            obj_list[i] != h_counter2 &&
+			obj_list[i] != h_clock) {
+
+            printf("%s:%d ERROR:  C_FindObjects #2 found the wrong\n"
+                   " objects!", __FILE__, __LINE__);
+            rc = -1;
         }
+    }
 
-        rc = funcs->C_FindObjectsFinal( sess );
-        if (rc != CKR_OK) {
-                show_error("   C_FindObjectsFinal #2", rc );
-        }
+    rc = funcs->C_FindObjectsFinal(sess);
+    if (rc != CKR_OK) {
+        show_error("   C_FindObjectsFinal #2", rc);
+    }
 
 done:
-	/* Destroy the created objects, don't clobber the rc */
-	funcs->C_DestroyObject(sess, h_clock);
+    /* Destroy the created objects, don't clobber the rc */
+    funcs->C_DestroyObject(sess, h_clock);
 destroy_4:
-	funcs->C_DestroyObject(sess, h_counter2);
+    funcs->C_DestroyObject(sess, h_counter2);
 destroy_3:
-	funcs->C_DestroyObject(sess, h_counter1);
+    funcs->C_DestroyObject(sess, h_counter1);
 destroy_2:
-	funcs->C_DestroyObject(sess, h_obj2);
+    funcs->C_DestroyObject(sess, h_obj2);
 destroy_1:
-	funcs->C_DestroyObject(sess, h_obj1);
+    funcs->C_DestroyObject(sess, h_obj1);
 
-	return rc;
+    return rc;
 }
 
 
diff --git a/usr/lib/pkcs11/common/hwf_obj.c b/usr/lib/pkcs11/common/hwf_obj.c
index 0decc22b..2a6ac45a 100644
--- a/usr/lib/pkcs11/common/hwf_obj.c
+++ b/usr/lib/pkcs11/common/hwf_obj.c
@@ -169,8 +169,8 @@ counter_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode)
       case CKA_HAS_RESET:
 	 /* Fall Through */
       case CKA_RESET_ON_INIT:
-            return CKR_OK;
-
+          TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
+          return CKR_ATTRIBUTE_READ_ONLY;
       default:
 	 return hwf_validate_attribute( tmpl, attr, mode );
    }
-- 
2.13.6

