diff --git a/tests/psa-client-server/psasim/src/psa_functions_codes.h b/tests/psa-client-server/psasim/src/psa_functions_codes.h index dd926d7137..44ebf678f4 100644 --- a/tests/psa-client-server/psasim/src/psa_functions_codes.h +++ b/tests/psa-client-server/psasim/src/psa_functions_codes.h @@ -36,6 +36,14 @@ enum { PSA_HASH_UPDATE, PSA_HASH_VERIFY, PSA_IMPORT_KEY, + PSA_MAC_ABORT, + PSA_MAC_COMPUTE, + PSA_MAC_SIGN_FINISH, + PSA_MAC_SIGN_SETUP, + PSA_MAC_UPDATE, + PSA_MAC_VERIFY, + PSA_MAC_VERIFY_FINISH, + PSA_MAC_VERIFY_SETUP, }; #endif /* _PSA_FUNCTIONS_CODES_H_ */ diff --git a/tests/psa-client-server/psasim/src/psa_sim_crypto_client.c b/tests/psa-client-server/psasim/src/psa_sim_crypto_client.c index 377b2369cf..844c93951d 100644 --- a/tests/psa-client-server/psasim/src/psa_sim_crypto_client.c +++ b/tests/psa-client-server/psasim/src/psa_sim_crypto_client.c @@ -1976,3 +1976,607 @@ fail: return status; } + + +psa_status_t psa_mac_abort( + psa_mac_operation_t *operation + ) +{ + uint8_t *params = NULL; + uint8_t *result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = psasim_serialise_begin_needs() + + psasim_serialise_psa_mac_operation_t_needs(*operation); + + params = malloc(needed); + if (params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_mac_operation_t(&pos, &remaining, *operation); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_MAC_ABORT, + params, (size_t) (pos - params), &result, &result_length); + if (!ok) { + printf("PSA_MAC_ABORT server call failed\n"); + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_mac_operation_t(&rpos, &rremain, operation); + if (!ok) { + goto fail; + } + +fail: + free(params); + free(result); + + return status; +} + + +psa_status_t psa_mac_compute( + mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + uint8_t *mac, size_t mac_size, + size_t *mac_length + ) +{ + uint8_t *params = NULL; + uint8_t *result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = psasim_serialise_begin_needs() + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg) + + psasim_serialise_buffer_needs(input, input_length) + + psasim_serialise_buffer_needs(mac, mac_size) + + psasim_serialise_size_t_needs(*mac_length); + + params = malloc(needed); + if (params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t(&pos, &remaining, key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t(&pos, &remaining, alg); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer(&pos, &remaining, input, input_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer(&pos, &remaining, mac, mac_size); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t(&pos, &remaining, *mac_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_MAC_COMPUTE, + params, (size_t) (pos - params), &result, &result_length); + if (!ok) { + printf("PSA_MAC_COMPUTE server call failed\n"); + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer(&rpos, &rremain, mac, mac_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t(&rpos, &rremain, mac_length); + if (!ok) { + goto fail; + } + +fail: + free(params); + free(result); + + return status; +} + + +psa_status_t psa_mac_sign_finish( + psa_mac_operation_t *operation, + uint8_t *mac, size_t mac_size, + size_t *mac_length + ) +{ + uint8_t *params = NULL; + uint8_t *result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = psasim_serialise_begin_needs() + + psasim_serialise_psa_mac_operation_t_needs(*operation) + + psasim_serialise_buffer_needs(mac, mac_size) + + psasim_serialise_size_t_needs(*mac_length); + + params = malloc(needed); + if (params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_mac_operation_t(&pos, &remaining, *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer(&pos, &remaining, mac, mac_size); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t(&pos, &remaining, *mac_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_MAC_SIGN_FINISH, + params, (size_t) (pos - params), &result, &result_length); + if (!ok) { + printf("PSA_MAC_SIGN_FINISH server call failed\n"); + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_mac_operation_t(&rpos, &rremain, operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer(&rpos, &rremain, mac, mac_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t(&rpos, &rremain, mac_length); + if (!ok) { + goto fail; + } + +fail: + free(params); + free(result); + + return status; +} + + +psa_status_t psa_mac_sign_setup( + psa_mac_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg + ) +{ + uint8_t *params = NULL; + uint8_t *result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = psasim_serialise_begin_needs() + + psasim_serialise_psa_mac_operation_t_needs(*operation) + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg); + + params = malloc(needed); + if (params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_mac_operation_t(&pos, &remaining, *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t(&pos, &remaining, key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t(&pos, &remaining, alg); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_MAC_SIGN_SETUP, + params, (size_t) (pos - params), &result, &result_length); + if (!ok) { + printf("PSA_MAC_SIGN_SETUP server call failed\n"); + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_mac_operation_t(&rpos, &rremain, operation); + if (!ok) { + goto fail; + } + +fail: + free(params); + free(result); + + return status; +} + + +psa_status_t psa_mac_update( + psa_mac_operation_t *operation, + const uint8_t *input, size_t input_length + ) +{ + uint8_t *params = NULL; + uint8_t *result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = psasim_serialise_begin_needs() + + psasim_serialise_psa_mac_operation_t_needs(*operation) + + psasim_serialise_buffer_needs(input, input_length); + + params = malloc(needed); + if (params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_mac_operation_t(&pos, &remaining, *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer(&pos, &remaining, input, input_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_MAC_UPDATE, + params, (size_t) (pos - params), &result, &result_length); + if (!ok) { + printf("PSA_MAC_UPDATE server call failed\n"); + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_mac_operation_t(&rpos, &rremain, operation); + if (!ok) { + goto fail; + } + +fail: + free(params); + free(result); + + return status; +} + + +psa_status_t psa_mac_verify( + mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + const uint8_t *mac, size_t mac_length + ) +{ + uint8_t *params = NULL; + uint8_t *result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = psasim_serialise_begin_needs() + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg) + + psasim_serialise_buffer_needs(input, input_length) + + psasim_serialise_buffer_needs(mac, mac_length); + + params = malloc(needed); + if (params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t(&pos, &remaining, key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t(&pos, &remaining, alg); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer(&pos, &remaining, input, input_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer(&pos, &remaining, mac, mac_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_MAC_VERIFY, + params, (size_t) (pos - params), &result, &result_length); + if (!ok) { + printf("PSA_MAC_VERIFY server call failed\n"); + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status); + if (!ok) { + goto fail; + } + +fail: + free(params); + free(result); + + return status; +} + + +psa_status_t psa_mac_verify_finish( + psa_mac_operation_t *operation, + const uint8_t *mac, size_t mac_length + ) +{ + uint8_t *params = NULL; + uint8_t *result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = psasim_serialise_begin_needs() + + psasim_serialise_psa_mac_operation_t_needs(*operation) + + psasim_serialise_buffer_needs(mac, mac_length); + + params = malloc(needed); + if (params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_mac_operation_t(&pos, &remaining, *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer(&pos, &remaining, mac, mac_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_MAC_VERIFY_FINISH, + params, (size_t) (pos - params), &result, &result_length); + if (!ok) { + printf("PSA_MAC_VERIFY_FINISH server call failed\n"); + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_mac_operation_t(&rpos, &rremain, operation); + if (!ok) { + goto fail; + } + +fail: + free(params); + free(result); + + return status; +} + + +psa_status_t psa_mac_verify_setup( + psa_mac_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg + ) +{ + uint8_t *params = NULL; + uint8_t *result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = psasim_serialise_begin_needs() + + psasim_serialise_psa_mac_operation_t_needs(*operation) + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg); + + params = malloc(needed); + if (params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_mac_operation_t(&pos, &remaining, *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t(&pos, &remaining, key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t(&pos, &remaining, alg); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_MAC_VERIFY_SETUP, + params, (size_t) (pos - params), &result, &result_length); + if (!ok) { + printf("PSA_MAC_VERIFY_SETUP server call failed\n"); + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_mac_operation_t(&rpos, &rremain, operation); + if (!ok) { + goto fail; + } + +fail: + free(params); + free(result); + + return status; +} diff --git a/tests/psa-client-server/psasim/src/psa_sim_crypto_server.c b/tests/psa-client-server/psasim/src/psa_sim_crypto_server.c index 0a84010f73..856186f6a3 100644 --- a/tests/psa-client-server/psasim/src/psa_sim_crypto_server.c +++ b/tests/psa-client-server/psasim/src/psa_sim_crypto_server.c @@ -2234,6 +2234,706 @@ fail: return 0; // This shouldn't happen! } +// Returns 1 for success, 0 for failure +int psa_mac_abort_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_mac_operation_t *operation; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_mac_operation_t(&pos, &remaining, &operation); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_mac_abort( + operation + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_mac_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t(&rpos, &rremain, status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_mac_operation_t(&rpos, &rremain, operation); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_mac_compute_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_svc_key_id_t key; + psa_algorithm_t alg; + uint8_t *input = NULL; + size_t input_length; + uint8_t *mac = NULL; + size_t mac_size; + size_t mac_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t(&pos, &remaining, &key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t(&pos, &remaining, &alg); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer(&pos, &remaining, &input, &input_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer(&pos, &remaining, &mac, &mac_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t(&pos, &remaining, &mac_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_mac_compute( + key, + alg, + input, input_length, + mac, mac_size, + &mac_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_serialise_buffer_needs(mac, mac_size) + + psasim_serialise_size_t_needs(mac_length); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t(&rpos, &rremain, status); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_buffer(&rpos, &rremain, mac, mac_size); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_size_t(&rpos, &rremain, mac_length); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(input); + free(mac); + + return 1; // success + +fail: + free(result); + + free(input); + free(mac); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_mac_sign_finish_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_mac_operation_t *operation; + uint8_t *mac = NULL; + size_t mac_size; + size_t mac_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_mac_operation_t(&pos, &remaining, &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer(&pos, &remaining, &mac, &mac_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t(&pos, &remaining, &mac_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_mac_sign_finish( + operation, + mac, mac_size, + &mac_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_mac_operation_t_needs(operation) + + psasim_serialise_buffer_needs(mac, mac_size) + + psasim_serialise_size_t_needs(mac_length); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t(&rpos, &rremain, status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_mac_operation_t(&rpos, &rremain, operation); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_buffer(&rpos, &rremain, mac, mac_size); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_size_t(&rpos, &rremain, mac_length); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(mac); + + return 1; // success + +fail: + free(result); + + free(mac); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_mac_sign_setup_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_mac_operation_t *operation; + mbedtls_svc_key_id_t key; + psa_algorithm_t alg; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_mac_operation_t(&pos, &remaining, &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t(&pos, &remaining, &key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t(&pos, &remaining, &alg); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_mac_sign_setup( + operation, + key, + alg + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_mac_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t(&rpos, &rremain, status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_mac_operation_t(&rpos, &rremain, operation); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_mac_update_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_mac_operation_t *operation; + uint8_t *input = NULL; + size_t input_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_mac_operation_t(&pos, &remaining, &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer(&pos, &remaining, &input, &input_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_mac_update( + operation, + input, input_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_mac_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t(&rpos, &rremain, status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_mac_operation_t(&rpos, &rremain, operation); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(input); + + return 1; // success + +fail: + free(result); + + free(input); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_mac_verify_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_svc_key_id_t key; + psa_algorithm_t alg; + uint8_t *input = NULL; + size_t input_length; + uint8_t *mac = NULL; + size_t mac_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t(&pos, &remaining, &key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t(&pos, &remaining, &alg); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer(&pos, &remaining, &input, &input_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer(&pos, &remaining, &mac, &mac_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_mac_verify( + key, + alg, + input, input_length, + mac, mac_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t(&rpos, &rremain, status); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(input); + free(mac); + + return 1; // success + +fail: + free(result); + + free(input); + free(mac); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_mac_verify_finish_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_mac_operation_t *operation; + uint8_t *mac = NULL; + size_t mac_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_mac_operation_t(&pos, &remaining, &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer(&pos, &remaining, &mac, &mac_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_mac_verify_finish( + operation, + mac, mac_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_mac_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t(&rpos, &rremain, status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_mac_operation_t(&rpos, &rremain, operation); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(mac); + + return 1; // success + +fail: + free(result); + + free(mac); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_mac_verify_setup_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_mac_operation_t *operation; + mbedtls_svc_key_id_t key; + psa_algorithm_t alg; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_mac_operation_t(&pos, &remaining, &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t(&pos, &remaining, &key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t(&pos, &remaining, &alg); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_mac_verify_setup( + operation, + key, + alg + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_mac_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t(&rpos, &rremain, status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_mac_operation_t(&rpos, &rremain, operation); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + psa_status_t psa_crypto_call(psa_msg_t msg) { int ok = 0; @@ -2370,6 +3070,38 @@ psa_status_t psa_crypto_call(psa_msg_t msg) ok = psa_import_key_wrapper(in_params, in_params_len, &out_params, &out_params_len); break; + case PSA_MAC_ABORT: + ok = psa_mac_abort_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_MAC_COMPUTE: + ok = psa_mac_compute_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_MAC_SIGN_FINISH: + ok = psa_mac_sign_finish_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_MAC_SIGN_SETUP: + ok = psa_mac_sign_setup_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_MAC_UPDATE: + ok = psa_mac_update_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_MAC_VERIFY: + ok = psa_mac_verify_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_MAC_VERIFY_FINISH: + ok = psa_mac_verify_finish_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_MAC_VERIFY_SETUP: + ok = psa_mac_verify_setup_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; } free(in_params); diff --git a/tests/psa-client-server/psasim/src/psa_sim_generate.pl b/tests/psa-client-server/psasim/src/psa_sim_generate.pl index b2a59b20f1..ea5088e7a5 100755 --- a/tests/psa-client-server/psasim/src/psa_sim_generate.pl +++ b/tests/psa-client-server/psasim/src/psa_sim_generate.pl @@ -2398,3 +2398,407 @@ psa_status_t psa_destroy_key(mbedtls_svc_key_id_t key); */ psa_status_t psa_generate_random(uint8_t *output, size_t output_size); + +/** Calculate the MAC (message authentication code) of a message. + * + * \note To verify the MAC of a message against an + * expected value, use psa_mac_verify() instead. + * Beware that comparing integrity or authenticity data such as + * MAC values with a function such as \c memcmp is risky + * because the time taken by the comparison may leak information + * about the MAC value which could allow an attacker to guess + * a valid MAC and thereby bypass security controls. + * + * \param key Identifier of the key to use for the operation. It + * must allow the usage PSA_KEY_USAGE_SIGN_MESSAGE. + * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_MAC(\p alg) is true). + * \param[in] input Buffer containing the input message. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] mac Buffer where the MAC value is to be written. + * \param mac_size Size of the \p mac buffer in bytes. + * \param[out] mac_length On success, the number of bytes + * that make up the MAC value. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a MAC algorithm. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p mac_size is too small + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE + * The key could not be retrieved from storage. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_compute(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *mac, + size_t mac_size, + size_t *mac_length); + +/** Calculate the MAC of a message and compare it with a reference value. + * + * \param key Identifier of the key to use for the operation. It + * must allow the usage PSA_KEY_USAGE_VERIFY_MESSAGE. + * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_MAC(\p alg) is true). + * \param[in] input Buffer containing the input message. + * \param input_length Size of the \p input buffer in bytes. + * \param[in] mac Buffer containing the expected MAC value. + * \param mac_length Size of the \p mac buffer in bytes. + * + * \retval #PSA_SUCCESS + * The expected MAC is identical to the actual MAC of the input. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The MAC of the message was calculated successfully, but it + * differs from the expected value. + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a MAC algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE + * The key could not be retrieved from storage. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_verify(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *mac, + size_t mac_length); + +/** The type of the state data structure for multipart MAC operations. + * + * Before calling any function on a MAC operation object, the application must + * initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_mac_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_mac_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_MAC_OPERATION_INIT, + * for example: + * \code + * psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_mac_operation_init() + * to the structure, for example: + * \code + * psa_mac_operation_t operation; + * operation = psa_mac_operation_init(); + * \endcode + * + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure. + * Implementation details can change in future versions without notice. */ +typedef struct psa_mac_operation_s psa_mac_operation_t; + +/** \def PSA_MAC_OPERATION_INIT + * + * This macro returns a suitable initializer for a MAC operation object of type + * #psa_mac_operation_t. + */ + +/** Return an initial value for a MAC operation object. + */ +static psa_mac_operation_t psa_mac_operation_init(void); + +/** Set up a multipart MAC calculation operation. + * + * This function sets up the calculation of the MAC + * (message authentication code) of a byte string. + * To verify the MAC of a message against an + * expected value, use psa_mac_verify_setup() instead. + * + * The sequence of operations to calculate a MAC is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_mac_operation_t, e.g. #PSA_MAC_OPERATION_INIT. + * -# Call psa_mac_sign_setup() to specify the algorithm and key. + * -# Call psa_mac_update() zero, one or more times, passing a fragment + * of the message each time. The MAC that is calculated is the MAC + * of the concatenation of these messages in order. + * -# At the end of the message, call psa_mac_sign_finish() to finish + * calculating the MAC value and retrieve it. + * + * If an error occurs at any step after a call to psa_mac_sign_setup(), the + * operation will need to be reset by a call to psa_mac_abort(). The + * application may call psa_mac_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_mac_sign_setup(), the application must + * eventually terminate the operation through one of the following methods: + * - A successful call to psa_mac_sign_finish(). + * - A call to psa_mac_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_mac_operation_t and not yet in use. + * \param key Identifier of the key to use for the operation. It + * must remain valid until the operation terminates. + * It must allow the usage PSA_KEY_USAGE_SIGN_MESSAGE. + * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_MAC(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a MAC algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE + * The key could not be retrieved from storage. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive), or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg); + +/** Set up a multipart MAC verification operation. + * + * This function sets up the verification of the MAC + * (message authentication code) of a byte string against an expected value. + * + * The sequence of operations to verify a MAC is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_mac_operation_t, e.g. #PSA_MAC_OPERATION_INIT. + * -# Call psa_mac_verify_setup() to specify the algorithm and key. + * -# Call psa_mac_update() zero, one or more times, passing a fragment + * of the message each time. The MAC that is calculated is the MAC + * of the concatenation of these messages in order. + * -# At the end of the message, call psa_mac_verify_finish() to finish + * calculating the actual MAC of the message and verify it against + * the expected value. + * + * If an error occurs at any step after a call to psa_mac_verify_setup(), the + * operation will need to be reset by a call to psa_mac_abort(). The + * application may call psa_mac_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_mac_verify_setup(), the application must + * eventually terminate the operation through one of the following methods: + * - A successful call to psa_mac_verify_finish(). + * - A call to psa_mac_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_mac_operation_t and not yet in use. + * \param key Identifier of the key to use for the operation. It + * must remain valid until the operation terminates. + * It must allow the usage + * PSA_KEY_USAGE_VERIFY_MESSAGE. + * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_MAC(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c key is not compatible with \c alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \c alg is not supported or is not a MAC algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE + * The key could not be retrieved from storage. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive), or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg); + +/** Add a message fragment to a multipart MAC operation. + * + * The application must call psa_mac_sign_setup() or psa_mac_verify_setup() + * before calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_mac_abort(). + * + * \param[in,out] operation Active MAC operation. + * \param[in] input Buffer containing the message fragment to add to + * the MAC calculation. + * \param input_length Size of the \p input buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active), or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_update(psa_mac_operation_t *operation, + const uint8_t *input, + size_t input_length); + +/** Finish the calculation of the MAC of a message. + * + * The application must call psa_mac_sign_setup() before calling this function. + * This function calculates the MAC of the message formed by concatenating + * the inputs passed to preceding calls to psa_mac_update(). + * + * When this function returns successfully, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_mac_abort(). + * + * \warning Applications should not call this function if they expect + * a specific value for the MAC. Call psa_mac_verify_finish() instead. + * Beware that comparing integrity or authenticity data such as + * MAC values with a function such as \c memcmp is risky + * because the time taken by the comparison may leak information + * about the MAC value which could allow an attacker to guess + * a valid MAC and thereby bypass security controls. + * + * \param[in,out] operation Active MAC operation. + * \param[out] mac Buffer where the MAC value is to be written. + * \param mac_size Size of the \p mac buffer in bytes. + * \param[out] mac_length On success, the number of bytes + * that make up the MAC value. This is always + * #PSA_MAC_LENGTH(\c key_type, \c key_bits, \c alg) + * where \c key_type and \c key_bits are the type and + * bit-size respectively of the key and \c alg is the + * MAC algorithm that is calculated. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p mac buffer is too small. You can determine a + * sufficient buffer size by calling PSA_MAC_LENGTH(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active mac sign + * operation), or the library has not been previously initialized + * by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation, + uint8_t *mac, + size_t mac_size, + size_t *mac_length); + +/** Finish the calculation of the MAC of a message and compare it with + * an expected value. + * + * The application must call psa_mac_verify_setup() before calling this function. + * This function calculates the MAC of the message formed by concatenating + * the inputs passed to preceding calls to psa_mac_update(). It then + * compares the calculated MAC with the expected MAC passed as a + * parameter to this function. + * + * When this function returns successfully, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_mac_abort(). + * + * \note Implementations shall make the best effort to ensure that the + * comparison between the actual MAC and the expected MAC is performed + * in constant time. + * + * \param[in,out] operation Active MAC operation. + * \param[in] mac Buffer containing the expected MAC value. + * \param mac_length Size of the \p mac buffer in bytes. + * + * \retval #PSA_SUCCESS + * The expected MAC is identical to the actual MAC of the message. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The MAC of the message was calculated successfully, but it + * differs from the expected MAC. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active mac verify + * operation), or the library has not been previously initialized + * by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation, + const uint8_t *mac, + size_t mac_length); + +/** Abort a MAC operation. + * + * Aborting an operation frees all associated resources except for the + * \p operation structure itself. Once aborted, the operation object + * can be reused for another operation by calling + * psa_mac_sign_setup() or psa_mac_verify_setup() again. + * + * You may call this function any time after the operation object has + * been initialized by one of the methods described in #psa_mac_operation_t. + * + * In particular, calling psa_mac_abort() after the operation has been + * terminated by a call to psa_mac_abort(), psa_mac_sign_finish() or + * psa_mac_verify_finish() is safe and has no effect. + * + * \param[in,out] operation Initialized MAC operation. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_abort(psa_mac_operation_t *operation); diff --git a/tests/psa-client-server/psasim/src/psa_sim_serialise.c b/tests/psa-client-server/psasim/src/psa_sim_serialise.c index 651e0468e2..0cd2e09f95 100644 --- a/tests/psa-client-server/psasim/src/psa_sim_serialise.c +++ b/tests/psa-client-server/psasim/src/psa_sim_serialise.c @@ -139,6 +139,44 @@ static ssize_t find_aead_slot_by_handle(psasim_client_handle_t handle) return -1; /* not found */ } +static psa_mac_operation_t mac_operations[MAX_LIVE_HANDLES_PER_CLASS]; +static psasim_client_handle_t mac_operation_handles[MAX_LIVE_HANDLES_PER_CLASS]; +static psasim_client_handle_t next_mac_operation_handle = 1; + +/* Get a free slot */ +static ssize_t allocate_mac_operation_slot(void) +{ + psasim_client_handle_t handle = next_mac_operation_handle++; + if (next_mac_operation_handle == 0) { /* wrapped around */ + FATAL("Mac operation handle wrapped"); + } + + for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) { + if (mac_operation_handles[i] == 0) { + mac_operation_handles[i] = handle; + return i; + } + } + + ERROR("All slots are currently used. Unable to allocate a new one."); + + return -1; /* all in use */ +} + +/* Find the slot given the handle */ +static ssize_t find_mac_slot_by_handle(psasim_client_handle_t handle) +{ + for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) { + if (mac_operation_handles[i] == handle) { + return i; + } + } + + ERROR("Unable to find slot by handle %u", handle); + + return -1; /* not found */ +} + size_t psasim_serialise_begin_needs(void) { /* The serialisation buffer will @@ -679,6 +717,99 @@ int psasim_deserialise_psa_key_attributes_t(uint8_t **pos, return 1; } +size_t psasim_serialise_psa_mac_operation_t_needs(psa_mac_operation_t value) +{ + return sizeof(value); +} + +int psasim_serialise_psa_mac_operation_t(uint8_t **pos, + size_t *remaining, + psa_mac_operation_t value) +{ + if (*remaining < sizeof(value)) { + return 0; + } + + memcpy(*pos, &value, sizeof(value)); + *pos += sizeof(value); + + return 1; +} + +int psasim_deserialise_psa_mac_operation_t(uint8_t **pos, + size_t *remaining, + psa_mac_operation_t *value) +{ + if (*remaining < sizeof(*value)) { + return 0; + } + + memcpy(value, *pos, sizeof(*value)); + + *pos += sizeof(*value); + *remaining -= sizeof(*value); + + return 1; +} + +size_t psasim_server_serialise_psa_mac_operation_t_needs(psa_mac_operation_t *operation) +{ + (void) operation; + + /* We will actually return a handle */ + return sizeof(psasim_operation_t); +} + +int psasim_server_serialise_psa_mac_operation_t(uint8_t **pos, + size_t *remaining, + psa_mac_operation_t *operation) +{ + psasim_operation_t client_operation; + + if (*remaining < sizeof(client_operation)) { + return 0; + } + + ssize_t slot = operation - mac_operations; + + client_operation.handle = mac_operation_handles[slot]; + + memcpy(*pos, &client_operation, sizeof(client_operation)); + *pos += sizeof(client_operation); + + return 1; +} + +int psasim_server_deserialise_psa_mac_operation_t(uint8_t **pos, + size_t *remaining, + psa_mac_operation_t **operation) +{ + psasim_operation_t client_operation; + + if (*remaining < sizeof(psasim_operation_t)) { + return 0; + } + + memcpy(&client_operation, *pos, sizeof(psasim_operation_t)); + *pos += sizeof(psasim_operation_t); + *remaining -= sizeof(psasim_operation_t); + + ssize_t slot; + if (client_operation.handle == 0) { /* We need a new handle */ + slot = allocate_mac_operation_slot(); + } else { + slot = find_mac_slot_by_handle(client_operation.handle); + } + + if (slot < 0) { + return 0; + } + + *operation = &mac_operations[slot]; + + return 1; +} + size_t psasim_serialise_mbedtls_svc_key_id_t_needs(mbedtls_svc_key_id_t value) { return sizeof(value); @@ -720,4 +851,6 @@ void psa_sim_serialize_reset(void) memset(hash_operations, 0, sizeof(hash_operations)); memset(aead_operation_handles, 0, sizeof(aead_operation_handles)); memset(aead_operations, 0, sizeof(aead_operations)); + memset(mac_operation_handles, 0, sizeof(mac_operation_handles)); + memset(mac_operations, 0, sizeof(mac_operations)); } diff --git a/tests/psa-client-server/psasim/src/psa_sim_serialise.h b/tests/psa-client-server/psasim/src/psa_sim_serialise.h index 537730c1f8..11de3d711a 100644 --- a/tests/psa-client-server/psasim/src/psa_sim_serialise.h +++ b/tests/psa-client-server/psasim/src/psa_sim_serialise.h @@ -583,6 +583,90 @@ int psasim_deserialise_psa_key_attributes_t(uint8_t **pos, size_t *remaining, psa_key_attributes_t *value); +/** Return how much buffer space is needed by \c psasim_serialise_psa_mac_operation_t() + * to serialise a `psa_mac_operation_t`. + * + * \param value The value that will be serialised into the buffer + * (needed in case some serialisations are value- + * dependent). + * + * \return The number of bytes needed in the buffer by + * \c psasim_serialise_psa_mac_operation_t() to serialise + * the given value. + */ +size_t psasim_serialise_psa_mac_operation_t_needs(psa_mac_operation_t value); + +/** Serialise a `psa_mac_operation_t` into a buffer. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value The value to serialise into the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_serialise_psa_mac_operation_t(uint8_t **pos, + size_t *remaining, + psa_mac_operation_t value); + +/** Deserialise a `psa_mac_operation_t` from a buffer. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value Pointer to a `psa_mac_operation_t` to receive the value + * deserialised from the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_deserialise_psa_mac_operation_t(uint8_t **pos, + size_t *remaining, + psa_mac_operation_t *value); + +/** Return how much buffer space is needed by \c psasim_server_serialise_psa_mac_operation_t() + * to serialise a `psa_mac_operation_t`. + * + * \param value The value that will be serialised into the buffer + * (needed in case some serialisations are value- + * dependent). + * + * \return The number of bytes needed in the buffer by + * \c psasim_serialise_psa_mac_operation_t() to serialise + * the given value. + */ +size_t psasim_server_serialise_psa_mac_operation_t_needs(psa_mac_operation_t *value); + +/** Serialise a `psa_mac_operation_t` into a buffer on the server side. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value The value to serialise into the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_server_serialise_psa_mac_operation_t(uint8_t **pos, + size_t *remaining, + psa_mac_operation_t *value); + +/** Deserialise a `psa_mac_operation_t` from a buffer on the server side. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value Pointer to a `psa_mac_operation_t` to receive the value + * deserialised from the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_server_deserialise_psa_mac_operation_t(uint8_t **pos, + size_t *remaining, + psa_mac_operation_t **value); + /** Return how much buffer space is needed by \c psasim_serialise_mbedtls_svc_key_id_t() * to serialise a `mbedtls_svc_key_id_t`. * diff --git a/tests/psa-client-server/psasim/src/psa_sim_serialise.pl b/tests/psa-client-server/psasim/src/psa_sim_serialise.pl index e89fafe0be..75f540b920 100755 --- a/tests/psa-client-server/psasim/src/psa_sim_serialise.pl +++ b/tests/psa-client-server/psasim/src/psa_sim_serialise.pl @@ -41,6 +41,7 @@ my @types = qw(unsigned-int int size_t psa_hash_operation_t psa_aead_operation_t psa_key_attributes_t + psa_mac_operation_t mbedtls_svc_key_id_t); grep(s/-/ /g, @types);