Add the rest of the psa_hash_xxx() functions to the simulator

Signed-off-by: Tom Cosgrove <tom.cosgrove@arm.com>
This commit is contained in:
Tom Cosgrove 2024-05-29 12:34:27 +01:00
parent 39f8b09f5b
commit 61ee59f041
4 changed files with 1338 additions and 0 deletions

View File

@ -12,7 +12,14 @@ enum {
/* Start here to avoid overlap with PSA_IPC_CONNECT, PSA_IPC_DISCONNECT
* and VERSION_REQUEST */
PSA_CRYPTO_INIT = 100,
PSA_HASH_ABORT,
PSA_HASH_CLONE,
PSA_HASH_COMPARE,
PSA_HASH_COMPUTE,
PSA_HASH_FINISH,
PSA_HASH_SETUP,
PSA_HASH_UPDATE,
PSA_HASH_VERIFY,
};
#endif /* _PSA_FUNCTIONS_CODES_H_ */

View File

@ -121,6 +121,208 @@ void mbedtls_psa_crypto_free(void)
}
psa_status_t psa_hash_abort(
psa_hash_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_hash_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_hash_operation_t(&pos, &remaining, *operation);
if (!ok) {
goto fail;
}
ok = psa_crypto_call(PSA_HASH_ABORT,
params, (size_t) (pos - params), &result, &result_length);
if (!ok) {
printf("XXX 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_hash_operation_t(&rpos, &rremain, operation);
if (!ok) {
goto fail;
}
fail:
free(params);
free(result);
return status;
}
psa_status_t psa_hash_clone(
const psa_hash_operation_t *source_operation,
psa_hash_operation_t *target_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_hash_operation_t_needs(*source_operation) +
psasim_serialise_psa_hash_operation_t_needs(*target_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_hash_operation_t(&pos, &remaining, *source_operation);
if (!ok) {
goto fail;
}
ok = psasim_serialise_psa_hash_operation_t(&pos, &remaining, *target_operation);
if (!ok) {
goto fail;
}
ok = psa_crypto_call(PSA_HASH_CLONE,
params, (size_t) (pos - params), &result, &result_length);
if (!ok) {
printf("XXX 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_hash_operation_t(&rpos, &rremain, target_operation);
if (!ok) {
goto fail;
}
fail:
free(params);
free(result);
return status;
}
psa_status_t psa_hash_compare(
psa_algorithm_t alg,
const uint8_t *input, size_t input_length,
const uint8_t *hash, size_t hash_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_algorithm_t_needs(alg) +
psasim_serialise_buffer_needs(input, input_length) +
psasim_serialise_buffer_needs(hash, hash_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_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, hash, hash_length);
if (!ok) {
goto fail;
}
ok = psa_crypto_call(PSA_HASH_COMPARE,
params, (size_t) (pos - params), &result, &result_length);
if (!ok) {
printf("XXX 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_hash_compute(
psa_algorithm_t alg,
const uint8_t *input, size_t input_length,
@ -205,3 +407,295 @@ fail:
return status;
}
psa_status_t psa_hash_finish(
psa_hash_operation_t *operation,
uint8_t *hash, size_t hash_size,
size_t *hash_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_hash_operation_t_needs(*operation) +
psasim_serialise_buffer_needs(hash, hash_size) +
psasim_serialise_size_t_needs(*hash_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_hash_operation_t(&pos, &remaining, *operation);
if (!ok) {
goto fail;
}
ok = psasim_serialise_buffer(&pos, &remaining, hash, hash_size);
if (!ok) {
goto fail;
}
ok = psasim_serialise_size_t(&pos, &remaining, *hash_length);
if (!ok) {
goto fail;
}
ok = psa_crypto_call(PSA_HASH_FINISH,
params, (size_t) (pos - params), &result, &result_length);
if (!ok) {
printf("XXX 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_hash_operation_t(&rpos, &rremain, operation);
if (!ok) {
goto fail;
}
ok = psasim_deserialise_return_buffer(&rpos, &rremain, hash, hash_size);
if (!ok) {
goto fail;
}
ok = psasim_deserialise_size_t(&rpos, &rremain, hash_length);
if (!ok) {
goto fail;
}
fail:
free(params);
free(result);
return status;
}
psa_status_t psa_hash_setup(
psa_hash_operation_t *operation,
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_hash_operation_t_needs(*operation) +
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_hash_operation_t(&pos, &remaining, *operation);
if (!ok) {
goto fail;
}
ok = psasim_serialise_psa_algorithm_t(&pos, &remaining, alg);
if (!ok) {
goto fail;
}
ok = psa_crypto_call(PSA_HASH_SETUP,
params, (size_t) (pos - params), &result, &result_length);
if (!ok) {
printf("XXX 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_hash_operation_t(&rpos, &rremain, operation);
if (!ok) {
goto fail;
}
fail:
free(params);
free(result);
return status;
}
psa_status_t psa_hash_update(
psa_hash_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_hash_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_hash_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_HASH_UPDATE,
params, (size_t) (pos - params), &result, &result_length);
if (!ok) {
printf("XXX 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_hash_operation_t(&rpos, &rremain, operation);
if (!ok) {
goto fail;
}
fail:
free(params);
free(result);
return status;
}
psa_status_t psa_hash_verify(
psa_hash_operation_t *operation,
const uint8_t *hash, size_t hash_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_hash_operation_t_needs(*operation) +
psasim_serialise_buffer_needs(hash, hash_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_hash_operation_t(&pos, &remaining, *operation);
if (!ok) {
goto fail;
}
ok = psasim_serialise_buffer(&pos, &remaining, hash, hash_length);
if (!ok) {
goto fail;
}
ok = psa_crypto_call(PSA_HASH_VERIFY,
params, (size_t) (pos - params), &result, &result_length);
if (!ok) {
printf("XXX 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_hash_operation_t(&rpos, &rremain, operation);
if (!ok) {
goto fail;
}
fail:
free(params);
free(result);
return status;
}

View File

@ -60,6 +60,227 @@ fail:
return 0; // This shouldn't happen!
}
// Returns 1 for success, 0 for failure
int psa_hash_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_hash_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_deserialise_psa_hash_operation_t(&pos, &remaining, &operation);
if (!ok) {
goto fail;
}
// Now we call the actual target function
status = psa_hash_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_serialise_psa_hash_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_serialise_psa_hash_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_hash_clone_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_hash_operation_t source_operation;
psa_hash_operation_t target_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_deserialise_psa_hash_operation_t(&pos, &remaining, &source_operation);
if (!ok) {
goto fail;
}
ok = psasim_deserialise_psa_hash_operation_t(&pos, &remaining, &target_operation);
if (!ok) {
goto fail;
}
// Now we call the actual target function
status = psa_hash_clone(
&source_operation,
&target_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_serialise_psa_hash_operation_t_needs(target_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_serialise_psa_hash_operation_t(&rpos, &rremain, target_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_hash_compare_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_algorithm_t alg;
uint8_t *input = NULL;
size_t input_length;
uint8_t *hash = NULL;
size_t hash_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_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, &hash, &hash_length);
if (!ok) {
goto fail;
}
// Now we call the actual target function
status = psa_hash_compare(
alg,
input, input_length,
hash, hash_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;
return 1; // success
fail:
free(result);
return 0; // This shouldn't happen!
}
// Returns 1 for success, 0 for failure
int psa_hash_compute_wrapper(
uint8_t *in_params, size_t in_params_len,
@ -157,6 +378,328 @@ fail:
return 0; // This shouldn't happen!
}
// Returns 1 for success, 0 for failure
int psa_hash_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_hash_operation_t operation;
uint8_t *hash = NULL;
size_t hash_size;
size_t hash_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_psa_hash_operation_t(&pos, &remaining, &operation);
if (!ok) {
goto fail;
}
ok = psasim_deserialise_buffer(&pos, &remaining, &hash, &hash_size);
if (!ok) {
goto fail;
}
ok = psasim_deserialise_size_t(&pos, &remaining, &hash_length);
if (!ok) {
goto fail;
}
// Now we call the actual target function
status = psa_hash_finish(
&operation,
hash, hash_size,
&hash_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_psa_hash_operation_t_needs(operation) +
psasim_serialise_buffer_needs(hash, hash_size) +
psasim_serialise_size_t_needs(hash_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_psa_hash_operation_t(&rpos, &rremain, operation);
if (!ok) {
goto fail;
}
ok = psasim_serialise_buffer(&rpos, &rremain, hash, hash_size);
if (!ok) {
goto fail;
}
ok = psasim_serialise_size_t(&rpos, &rremain, hash_length);
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_hash_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_hash_operation_t operation;
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_deserialise_psa_hash_operation_t(&pos, &remaining, &operation);
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_hash_setup(
&operation,
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_serialise_psa_hash_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_serialise_psa_hash_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_hash_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_hash_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_deserialise_psa_hash_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_hash_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_serialise_psa_hash_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_serialise_psa_hash_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_hash_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;
psa_hash_operation_t operation;
uint8_t *hash = NULL;
size_t hash_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_psa_hash_operation_t(&pos, &remaining, &operation);
if (!ok) {
goto fail;
}
ok = psasim_deserialise_buffer(&pos, &remaining, &hash, &hash_length);
if (!ok) {
goto fail;
}
// Now we call the actual target function
status = psa_hash_verify(
&operation,
hash, hash_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_psa_hash_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_serialise_psa_hash_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;
@ -197,10 +740,38 @@ psa_status_t psa_crypto_call(psa_msg_t msg)
ok = psa_crypto_init_wrapper(in_params, in_params_len,
&out_params, &out_params_len);
break;
case PSA_HASH_ABORT:
ok = psa_hash_abort_wrapper(in_params, in_params_len,
&out_params, &out_params_len);
break;
case PSA_HASH_CLONE:
ok = psa_hash_clone_wrapper(in_params, in_params_len,
&out_params, &out_params_len);
break;
case PSA_HASH_COMPARE:
ok = psa_hash_compare_wrapper(in_params, in_params_len,
&out_params, &out_params_len);
break;
case PSA_HASH_COMPUTE:
ok = psa_hash_compute_wrapper(in_params, in_params_len,
&out_params, &out_params_len);
break;
case PSA_HASH_FINISH:
ok = psa_hash_finish_wrapper(in_params, in_params_len,
&out_params, &out_params_len);
break;
case PSA_HASH_SETUP:
ok = psa_hash_setup_wrapper(in_params, in_params_len,
&out_params, &out_params_len);
break;
case PSA_HASH_UPDATE:
ok = psa_hash_update_wrapper(in_params, in_params_len,
&out_params, &out_params_len);
break;
case PSA_HASH_VERIFY:
ok = psa_hash_verify_wrapper(in_params, in_params_len,
&out_params, &out_params_len);
break;
}
free(in_params);

View File

@ -1128,3 +1128,269 @@ psa_status_t psa_hash_compute(psa_algorithm_t alg,
uint8_t *hash,
size_t hash_size,
size_t *hash_length);
/* XXX We put this next one in place to check we ignore static functions
* when we eventually read all this from a real header file
*/
/** Return an initial value for a hash operation object.
*/
static psa_hash_operation_t psa_hash_operation_init(void);
/* XXX Back to normal function declarations */
/** Set up a multipart hash operation.
*
* The sequence of operations to calculate a hash (message digest)
* 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_hash_operation_t, e.g. #PSA_HASH_OPERATION_INIT.
* -# Call psa_hash_setup() to specify the algorithm.
* -# Call psa_hash_update() zero, one or more times, passing a fragment
* of the message each time. The hash that is calculated is the hash
* of the concatenation of these messages in order.
* -# To calculate the hash, call psa_hash_finish().
* To compare the hash with an expected value, call psa_hash_verify().
*
* If an error occurs at any step after a call to psa_hash_setup(), the
* operation will need to be reset by a call to psa_hash_abort(). The
* application may call psa_hash_abort() at any time after the operation
* has been initialized.
*
* After a successful call to psa_hash_setup(), the application must
* eventually terminate the operation. The following events terminate an
* operation:
* - A successful call to psa_hash_finish() or psa_hash_verify().
* - A call to psa_hash_abort().
*
* \param[in,out] operation The operation object to set up. It must have
* been initialized as per the documentation for
* #psa_hash_operation_t and not yet in use.
* \param alg The hash algorithm to compute (\c PSA_ALG_XXX value
* such that #PSA_ALG_IS_HASH(\p alg) is true).
*
* \retval #PSA_SUCCESS
* Success.
* \retval #PSA_ERROR_NOT_SUPPORTED
* \p alg is not a supported hash algorithm.
* \retval #PSA_ERROR_INVALID_ARGUMENT
* \p alg is not a hash 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_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_hash_setup(psa_hash_operation_t *operation,
psa_algorithm_t alg);
/** Add a message fragment to a multipart hash operation.
*
* The application must call psa_hash_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_hash_abort().
*
* \param[in,out] operation Active hash operation.
* \param[in] input Buffer containing the message fragment to hash.
* \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_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_hash_update(psa_hash_operation_t *operation,
const uint8_t *input,
size_t input_length);
/** Finish the calculation of the hash of a message.
*
* The application must call psa_hash_setup() before calling this function.
* This function calculates the hash of the message formed by concatenating
* the inputs passed to preceding calls to psa_hash_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_hash_abort().
*
* \warning Applications should not call this function if they expect
* a specific value for the hash. Call psa_hash_verify() instead.
* Beware that comparing integrity or authenticity data such as
* hash values with a function such as \c memcmp is risky
* because the time taken by the comparison may leak information
* about the hashed data which could allow an attacker to guess
* a valid hash and thereby bypass security controls.
*
* \param[in,out] operation Active hash operation.
* \param[out] hash Buffer where the hash is to be written.
* \param hash_size Size of the \p hash buffer in bytes.
* \param[out] hash_length On success, the number of bytes
* that make up the hash value. This is always
* #PSA_HASH_LENGTH(\c alg) where \c alg is the
* hash algorithm that is calculated.
*
* \retval #PSA_SUCCESS
* Success.
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* The size of the \p hash buffer is too small. You can determine a
* sufficient buffer size by calling #PSA_HASH_LENGTH(\c alg)
* where \c alg is the hash algorithm that is calculated.
* \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_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_hash_finish(psa_hash_operation_t *operation,
uint8_t *hash,
size_t hash_size,
size_t *hash_length);
/** Finish the calculation of the hash of a message and compare it with
* an expected value.
*
* The application must call psa_hash_setup() before calling this function.
* This function calculates the hash of the message formed by concatenating
* the inputs passed to preceding calls to psa_hash_update(). It then
* compares the calculated hash with the expected hash 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_hash_abort().
*
* \note Implementations shall make the best effort to ensure that the
* comparison between the actual hash and the expected hash is performed
* in constant time.
*
* \param[in,out] operation Active hash operation.
* \param[in] hash Buffer containing the expected hash value.
* \param hash_length Size of the \p hash buffer in bytes.
*
* \retval #PSA_SUCCESS
* The expected hash is identical to the actual hash of the message.
* \retval #PSA_ERROR_INVALID_SIGNATURE
* The hash of the message was calculated successfully, but it
* differs from the expected hash.
* \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_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_hash_verify(psa_hash_operation_t *operation,
const uint8_t *hash,
size_t hash_length);
/** Abort a hash 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_hash_setup() again.
*
* You may call this function any time after the operation object has
* been initialized by one of the methods described in #psa_hash_operation_t.
*
* In particular, calling psa_hash_abort() after the operation has been
* terminated by a call to psa_hash_abort(), psa_hash_finish() or
* psa_hash_verify() is safe and has no effect.
*
* \param[in,out] operation Initialized hash 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_hash_abort(psa_hash_operation_t *operation);
/** Clone a hash operation.
*
* This function copies the state of an ongoing hash operation to
* a new operation object. In other words, this function is equivalent
* to calling psa_hash_setup() on \p target_operation with the same
* algorithm that \p source_operation was set up for, then
* psa_hash_update() on \p target_operation with the same input that
* that was passed to \p source_operation. After this function returns, the
* two objects are independent, i.e. subsequent calls involving one of
* the objects do not affect the other object.
*
* \param[in] source_operation The active hash operation to clone.
* \param[in,out] target_operation The operation object to set up.
* It must be initialized but not active.
*
* \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_INSUFFICIENT_MEMORY \emptydescription
* \retval #PSA_ERROR_BAD_STATE
* The \p source_operation state is not valid (it must be active), or
* the \p target_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_hash_clone(const psa_hash_operation_t *source_operation,
psa_hash_operation_t *target_operation);
/** Calculate the hash (digest) of a message and compare it with a
* reference value.
*
* \param alg The hash algorithm to compute (\c PSA_ALG_XXX value
* such that #PSA_ALG_IS_HASH(\p alg) is true).
* \param[in] input Buffer containing the message to hash.
* \param input_length Size of the \p input buffer in bytes.
* \param[out] hash Buffer containing the expected hash value.
* \param hash_length Size of the \p hash buffer in bytes.
*
* \retval #PSA_SUCCESS
* The expected hash is identical to the actual hash of the input.
* \retval #PSA_ERROR_INVALID_SIGNATURE
* The hash of the message was calculated successfully, but it
* differs from the expected hash.
* \retval #PSA_ERROR_NOT_SUPPORTED
* \p alg is not supported or is not a hash algorithm.
* \retval #PSA_ERROR_INVALID_ARGUMENT
* \p input_length or \p hash_length do not match the hash size for \p alg
* \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_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_hash_compare(psa_algorithm_t alg,
const uint8_t *input,
size_t input_length,
const uint8_t *hash,
size_t hash_length);