Basic tests

Sign Hash, Verify Hash and Sign and Verify Hash.

Signed-off-by: Paul Elliott <paul.elliott@arm.com>
diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function
index c414b65..9bf5039 100644
--- a/tests/suites/test_suite_psa_crypto.function
+++ b/tests/suites/test_suite_psa_crypto.function
@@ -6444,6 +6444,89 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE */
+void sign_hash_interruptible(int key_type_arg, data_t *key_data,
+                             int alg_arg, data_t *input_data,
+                             data_t *output_data)
+{
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    size_t key_bits;
+    unsigned char *signature = NULL;
+    size_t signature_size;
+    size_t signature_length = 0xdeadbeef;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_status_t status = PSA_OPERATION_INCOMPLETE;
+    size_t num_ops = 0;
+    size_t num_ops_prior = 0;
+    psa_sign_hash_interruptible_operation_t operation =
+        psa_sign_hash_interruptible_operation_init();
+
+    PSA_ASSERT(psa_crypto_init());
+
+    psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);
+    psa_set_key_algorithm(&attributes, alg);
+    psa_set_key_type(&attributes, key_type);
+
+    PSA_ASSERT(psa_import_key(&attributes, key_data->x, key_data->len,
+                              &key));
+    PSA_ASSERT(psa_get_key_attributes(key, &attributes));
+    key_bits = psa_get_key_bits(&attributes);
+
+    /* Allocate a buffer which has the size advertised by the
+     * library. */
+    signature_size = PSA_SIGN_OUTPUT_SIZE(key_type,
+                                          key_bits, alg);
+    TEST_ASSERT(signature_size != 0);
+    TEST_LE_U(signature_size, PSA_SIGNATURE_MAX_SIZE);
+    ASSERT_ALLOC(signature, signature_size);
+
+    num_ops_prior = psa_sign_hash_get_num_ops(&operation);
+    TEST_ASSERT(num_ops_prior == 0);
+
+    /* Start performing the signature. */
+    PSA_ASSERT(psa_sign_hash_start(&operation, key, alg,
+                                   input_data->x, input_data->len));
+
+    num_ops_prior = psa_sign_hash_get_num_ops(&operation);
+    TEST_ASSERT(num_ops_prior == 0);
+
+    /* Continue performing the signature until complete. */
+    while (status == PSA_OPERATION_INCOMPLETE) {
+        status = psa_sign_hash_complete(&operation, signature, signature_size,
+                                        &signature_length);
+
+        if (status == PSA_SUCCESS || status == PSA_OPERATION_INCOMPLETE) {
+            num_ops = psa_sign_hash_get_num_ops(&operation);
+
+            TEST_ASSERT(num_ops > num_ops_prior);
+            num_ops_prior = num_ops;
+        }
+    }
+
+    TEST_ASSERT(status == PSA_SUCCESS);
+
+    /* Verify that the signature is what is expected. */
+    ASSERT_COMPARE(output_data->x, output_data->len,
+                   signature, signature_length);
+
+    PSA_ASSERT(psa_sign_hash_abort(&operation));
+
+exit:
+
+    /*
+     * Key attributes may have been returned by psa_get_key_attributes()
+     * thus reset them as required.
+     */
+    psa_reset_key_attributes(&attributes);
+
+    psa_destroy_key(key);
+    mbedtls_free(signature);
+    PSA_DONE();
+}
+/* END_CASE */
+
 /* BEGIN_CASE */
 void sign_hash_fail(int key_type_arg, data_t *key_data,
                     int alg_arg, data_t *input_data,
@@ -6559,6 +6642,116 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE */
+void sign_verify_hash_interruptible(int key_type_arg, data_t *key_data,
+                                    int alg_arg, data_t *input_data)
+{
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    size_t key_bits;
+    unsigned char *signature = NULL;
+    size_t signature_size;
+    size_t signature_length = 0xdeadbeef;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_status_t status = PSA_OPERATION_INCOMPLETE;
+    psa_sign_hash_interruptible_operation_t sign_operation =
+        psa_sign_hash_interruptible_operation_init();
+    psa_verify_hash_interruptible_operation_t verify_operation =
+        psa_verify_hash_interruptible_operation_init();
+
+    PSA_ASSERT(psa_crypto_init());
+
+    psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH);
+    psa_set_key_algorithm(&attributes, alg);
+    psa_set_key_type(&attributes, key_type);
+
+    PSA_ASSERT(psa_import_key(&attributes, key_data->x, key_data->len,
+                              &key));
+    PSA_ASSERT(psa_get_key_attributes(key, &attributes));
+    key_bits = psa_get_key_bits(&attributes);
+
+    /* Allocate a buffer which has the size advertised by the
+     * library. */
+    signature_size = PSA_SIGN_OUTPUT_SIZE(key_type,
+                                          key_bits, alg);
+    TEST_ASSERT(signature_size != 0);
+    TEST_LE_U(signature_size, PSA_SIGNATURE_MAX_SIZE);
+    ASSERT_ALLOC(signature, signature_size);
+
+    /* Start performing the signature. */
+    PSA_ASSERT(psa_sign_hash_start(&sign_operation, key, alg,
+                                   input_data->x, input_data->len));
+
+    /* Continue performing the signature until complete. */
+    while (status == PSA_OPERATION_INCOMPLETE) {
+
+        status = psa_sign_hash_complete(&sign_operation, signature, signature_size,
+                                        &signature_length);
+    }
+
+    TEST_ASSERT(status == PSA_SUCCESS);
+
+    PSA_ASSERT(psa_sign_hash_abort(&sign_operation));
+
+    /* Check that the signature length looks sensible. */
+    TEST_LE_U(signature_length, signature_size);
+    TEST_ASSERT(signature_length > 0);
+
+    status = PSA_OPERATION_INCOMPLETE;
+
+    /* Start verification. */
+    PSA_ASSERT(psa_verify_hash_start(&verify_operation, key, alg,
+                                     input_data->x, input_data->len,
+                                     signature, signature_length));
+
+    /* Continue performing the signature until complete. */
+    while (status == PSA_OPERATION_INCOMPLETE) {
+        status = psa_verify_hash_complete(&verify_operation);
+    }
+
+    TEST_ASSERT(status == PSA_SUCCESS);
+
+    PSA_ASSERT(psa_verify_hash_abort(&verify_operation));
+
+    verify_operation = psa_verify_hash_interruptible_operation_init();
+
+    if (input_data->len != 0) {
+        /* Flip a bit in the input and verify that the signature is now
+         * detected as invalid. Flip a bit at the beginning, not at the end,
+         * because ECDSA may ignore the last few bits of the input. */
+        input_data->x[0] ^= 1;
+
+        status = PSA_OPERATION_INCOMPLETE;
+
+        /* Start verification. */
+        PSA_ASSERT(psa_verify_hash_start(&verify_operation, key, alg,
+                                         input_data->x, input_data->len,
+                                         signature, signature_length));
+
+        /* Continue performing the signature until complete. */
+        while (status == PSA_OPERATION_INCOMPLETE) {
+            status = psa_verify_hash_complete(&verify_operation);
+        }
+
+        TEST_ASSERT(status ==  PSA_ERROR_INVALID_SIGNATURE);
+    }
+
+    PSA_ASSERT(psa_verify_hash_abort(&verify_operation));
+
+exit:
+    /*
+     * Key attributes may have been returned by psa_get_key_attributes()
+     * thus reset them as required.
+     */
+    psa_reset_key_attributes(&attributes);
+
+    psa_destroy_key(key);
+    mbedtls_free(signature);
+    PSA_DONE();
+}
+/* END_CASE */
+
 /* BEGIN_CASE */
 void verify_hash(int key_type_arg, data_t *key_data,
                  int alg_arg, data_t *hash_data,
@@ -6591,6 +6784,71 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE */
+void verify_hash_interruptible(int key_type_arg, data_t *key_data,
+                               int alg_arg, data_t *hash_data,
+                               data_t *signature_data)
+{
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_status_t status = PSA_OPERATION_INCOMPLETE;
+    size_t num_ops = 0;
+    size_t num_ops_prior = 0;
+    psa_verify_hash_interruptible_operation_t operation =
+        psa_verify_hash_interruptible_operation_init();
+
+    TEST_LE_U(signature_data->len, PSA_SIGNATURE_MAX_SIZE);
+
+    PSA_ASSERT(psa_crypto_init());
+
+    psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH);
+    psa_set_key_algorithm(&attributes, alg);
+    psa_set_key_type(&attributes, key_type);
+
+    PSA_ASSERT(psa_import_key(&attributes, key_data->x, key_data->len,
+                              &key));
+
+    num_ops_prior = psa_verify_hash_get_num_ops(&operation);
+
+    TEST_ASSERT(num_ops_prior == 0);
+
+    /* Start verification. */
+    PSA_ASSERT(psa_verify_hash_start(&operation, key, alg,
+                                     hash_data->x, hash_data->len,
+                                     signature_data->x, signature_data->len)
+               );
+
+    num_ops_prior = psa_verify_hash_get_num_ops(&operation);
+
+    TEST_ASSERT(num_ops_prior == 0);
+
+    /* Continue performing the signature until complete. */
+    while (status == PSA_OPERATION_INCOMPLETE) {
+        status = psa_verify_hash_complete(&operation);
+
+        if (status == PSA_SUCCESS || status == PSA_OPERATION_INCOMPLETE) {
+            num_ops = psa_verify_hash_get_num_ops(&operation);
+
+            TEST_ASSERT(num_ops > num_ops_prior);
+            num_ops_prior = num_ops;
+        }
+    }
+
+    TEST_ASSERT(status == PSA_SUCCESS);
+
+    PSA_ASSERT(psa_verify_hash_abort(&operation));
+
+exit:
+    psa_reset_key_attributes(&attributes);
+    psa_destroy_key(key);
+    PSA_DONE();
+}
+/* END_CASE */
+
+
+
 /* BEGIN_CASE */
 void verify_hash_fail(int key_type_arg, data_t *key_data,
                       int alg_arg, data_t *hash_data,