Use libpsa in ts-demo
Modify the demo application to use the prebuilt PSA clients from
libpsa instead of directly building these.
Signed-off-by: Gabor Toth <gabor.toth2@arm.com>
Change-Id: Ib714c7ad901039c56ec6b021ff052b0329c79605
diff --git a/components/app/ts-demo/ts-demo.c b/components/app/ts-demo/ts-demo.c
new file mode 100644
index 0000000..43b3adb
--- /dev/null
+++ b/components/app/ts-demo/ts-demo.c
@@ -0,0 +1,325 @@
+/*
+ * Copyright (c) 2020-2023, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "ts-demo.h"
+
+#include <psa/crypto.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static const psa_key_id_t SIGNING_KEY_ID = 0x100;
+static const psa_key_id_t ENCRYPTION_KEY_ID = 0x101;
+
+bool m_verbose = true;
+
+void print_intro(void)
+{
+ if (m_verbose) {
+ printf("\nDemonstrates use of trusted services from an application");
+ printf("\n---------------------------------------------------------");
+ printf("\nA client requests a set of crypto operations performed by");
+ printf("\nthe Crypto service. Key storage for persistent keys is");
+ printf("\nprovided by the Secure Storage service via the ITS client.\n");
+ printf("\n");
+ }
+}
+
+void wait(int seconds)
+{
+ if (m_verbose)
+ sleep(seconds);
+}
+
+void print_status(psa_status_t status)
+{
+ if (m_verbose) {
+ if (status == PSA_SUCCESS)
+ printf("\n\tOperation successful\n");
+ else
+ printf("\n\tOperation failed. op error: %d\n", status);
+ }
+}
+
+void print_byte_array(const uint8_t *array, size_t len)
+{
+ size_t count = 0;
+ size_t column = 0;
+
+ while (count < len) {
+ if (column == 0)
+ printf("\n\t\t");
+ else
+ printf(" ");
+
+ printf("%02X", array[count]);
+
+ ++count;
+ column = (column + 1) % 8;
+ }
+
+ printf("\n");
+}
+
+bool generate_signing_key(psa_key_id_t *signing_key_id)
+{
+ psa_status_t status = PSA_ERROR_GENERIC_ERROR;
+ psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+ psa_set_key_id(&attributes, SIGNING_KEY_ID);
+ psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH);
+ psa_set_key_algorithm(&attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256));
+ psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
+ psa_set_key_bits(&attributes, 256);
+
+ if (m_verbose)
+ printf("Generating ECC signing key");
+
+ status = psa_generate_key(&attributes, signing_key_id);
+ psa_reset_key_attributes(&attributes);
+
+ print_status(status);
+
+ return (status != PSA_SUCCESS);
+}
+
+bool sign_and_verify_message(const char *message, psa_key_id_t signing_key_id)
+{
+ psa_status_t status = PSA_ERROR_GENERIC_ERROR;
+ bool error = false;
+ uint8_t message_buffer[100];
+ size_t message_len = strlen(message) + 1;
+
+ if (message_len > sizeof(message_buffer))
+ message_len = sizeof(message_buffer) - 1;
+
+ memset(message_buffer, 0, sizeof(message_buffer));
+ memcpy(message_buffer, message, message_len);
+
+ /* Sign message */
+ uint8_t signature[PSA_SIGNATURE_MAX_SIZE];
+ size_t signature_length;
+
+ if (m_verbose)
+ printf("Signing message: \"%s\" using key: %d", message_buffer, signing_key_id);
+
+ status = psa_sign_hash(signing_key_id, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256),
+ message_buffer, message_len, signature, sizeof(signature),
+ &signature_length);
+
+ print_status(status);
+
+ if (m_verbose && (status == PSA_SUCCESS)) {
+ printf("\tSignature bytes: ");
+ print_byte_array(signature, signature_length);
+ }
+
+ error |= (status != PSA_SUCCESS);
+
+ /* Verify signature against original message */
+ if (m_verbose)
+ printf("Verify signature using original message: \"%s\"", message_buffer);
+
+ status = psa_verify_hash(signing_key_id, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256),
+ message_buffer, message_len, signature, signature_length);
+
+ print_status(status);
+
+ error |= (status != PSA_SUCCESS);
+
+ /* Verify signature against modified message */
+ message_buffer[0] = '!';
+ if (m_verbose)
+ printf("Verify signature using modified message: \"%s\"", message_buffer);
+
+ status = psa_verify_hash(signing_key_id, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256),
+ message_buffer, message_len, signature, signature_length);
+
+ if (status == PSA_ERROR_INVALID_SIGNATURE) {
+ if (m_verbose)
+ printf("\n\tSuccessfully detected modified message\n");
+ } else {
+ print_status(status);
+ }
+
+ error |= (status == PSA_SUCCESS);
+
+ return error;
+}
+
+bool generate_asymmetric_encryption_key(psa_key_id_t *encryption_key_id)
+{
+ psa_status_t status = PSA_ERROR_GENERIC_ERROR;
+ psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+ psa_set_key_id(&attributes, ENCRYPTION_KEY_ID);
+ psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
+ psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_CRYPT);
+ psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR);
+ psa_set_key_bits(&attributes, 1024);
+
+ if (m_verbose)
+ printf("Generating RSA encryption key");
+
+ status = psa_generate_key(&attributes, encryption_key_id);
+ psa_reset_key_attributes(&attributes);
+
+ print_status(status);
+
+ return (status != PSA_SUCCESS);
+}
+
+bool encrypt_add_decrypt_message(const char *message, psa_key_id_t encryption_key_id)
+{
+ bool error = false;
+ psa_status_t status = PSA_ERROR_GENERIC_ERROR;
+ size_t message_len = strlen(message) + 1;
+
+ /* Encrypt a message */
+ if (m_verbose)
+ printf("Encrypt message: \"%s\" using RSA key: %d", message, encryption_key_id);
+
+ uint8_t ciphertext[256];
+ size_t ciphertext_len = 0;
+
+ status = psa_asymmetric_encrypt(encryption_key_id, PSA_ALG_RSA_PKCS1V15_CRYPT,
+ (const uint8_t *)message, message_len, NULL, 0, ciphertext,
+ sizeof(ciphertext), &ciphertext_len);
+ print_status(status);
+
+ if (m_verbose && (status == PSA_SUCCESS)) {
+ printf("\tEncrypted message: ");
+ print_byte_array(ciphertext, ciphertext_len);
+ }
+
+ error |= (status != PSA_SUCCESS);
+
+ /* Decrypt it */
+ if (m_verbose)
+ printf("Decrypting message using RSA key: %d", encryption_key_id);
+
+ uint8_t plaintext[256];
+ size_t plaintext_len = 0;
+
+ status = psa_asymmetric_decrypt(encryption_key_id, PSA_ALG_RSA_PKCS1V15_CRYPT, ciphertext,
+ ciphertext_len, NULL, 0, plaintext, sizeof(plaintext),
+ &plaintext_len);
+ print_status(status);
+
+ if (m_verbose && (status == PSA_SUCCESS)) {
+ if ((plaintext_len == message_len) &&
+ (memcmp(message, plaintext, plaintext_len) == 0)) {
+ printf("\tDecrypted message: \"%s\"\n", plaintext);
+ } else {
+ printf("\tDecrypted message is different from original!: ");
+ print_byte_array(plaintext, plaintext_len);
+ }
+ }
+
+ error |= (status != PSA_SUCCESS);
+
+ return error;
+}
+
+bool export_public_key(psa_key_id_t signing_key_id)
+{
+ psa_status_t status = PSA_ERROR_GENERIC_ERROR;
+ uint8_t key_buf[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE];
+ size_t key_len = 0;
+
+ if (m_verbose)
+ printf("Exporting public key: %d", signing_key_id);
+
+ status = psa_export_public_key(signing_key_id, key_buf, sizeof(key_buf), &key_len);
+
+ print_status(status);
+
+ if (m_verbose && (status == PSA_SUCCESS)) {
+ printf("\tPublic key bytes: ");
+ print_byte_array(key_buf, key_len);
+ }
+
+ return (status != PSA_SUCCESS);
+}
+
+bool generate_random_number(size_t length)
+{
+ psa_status_t status = PSA_ERROR_GENERIC_ERROR;
+ uint8_t *buffer = (uint8_t *)malloc(length);
+
+ if (m_verbose)
+ printf("Generating random bytes length: %lu", length);
+
+ status = psa_generate_random(buffer, length);
+
+ print_status(status);
+
+ if (m_verbose && (status == PSA_SUCCESS)) {
+ printf("\tRandom bytes: ");
+ print_byte_array(buffer, length);
+ }
+
+ return (status != PSA_SUCCESS);
+}
+
+bool destroy_keys(psa_key_id_t signing_key_id, psa_key_id_t encryption_key_id)
+{
+ bool error = false;
+ psa_status_t status = PSA_ERROR_GENERIC_ERROR;
+
+ if (m_verbose)
+ printf("Destroying signing key: %d", signing_key_id);
+
+ status = psa_destroy_key(signing_key_id);
+ print_status(status);
+ error |= (status != PSA_SUCCESS);
+
+ if (m_verbose)
+ printf("Destroying encryption key: %d", encryption_key_id);
+
+ status = psa_destroy_key(encryption_key_id);
+ print_status(status);
+ error |= (status != PSA_SUCCESS);
+
+ return error;
+}
+
+bool run_ts_demo(bool is_verbose)
+{
+ psa_key_id_t signing_key_id = 0;
+ psa_key_id_t encryption_key_id = 0;
+ bool error = false;
+
+ m_verbose = is_verbose;
+ print_intro();
+ wait(1);
+ psa_crypto_init();
+ wait(1);
+ error |= generate_random_number(1);
+ wait(1);
+ error |= generate_random_number(7);
+ wait(1);
+ error |= generate_random_number(128);
+ wait(1);
+ error |= generate_signing_key(&signing_key_id);
+ wait(2);
+ error |= sign_and_verify_message("The quick brown fox", signing_key_id);
+ wait(3);
+ error |= sign_and_verify_message("jumps over the lazy dog", signing_key_id);
+ wait(3);
+ error |= generate_asymmetric_encryption_key(&encryption_key_id);
+ wait(2);
+ error |= encrypt_add_decrypt_message("Top secret", encryption_key_id);
+ wait(3);
+ error |= export_public_key(signing_key_id);
+ wait(2);
+ error |= destroy_keys(signing_key_id, encryption_key_id);
+ wait(2);
+
+ return error;
+}