diff options
Diffstat (limited to 'components/app/ts-demo/ts-demo.cpp')
-rw-r--r-- | components/app/ts-demo/ts-demo.cpp | 329 |
1 files changed, 329 insertions, 0 deletions
diff --git a/components/app/ts-demo/ts-demo.cpp b/components/app/ts-demo/ts-demo.cpp new file mode 100644 index 000000000..637fd908c --- /dev/null +++ b/components/app/ts-demo/ts-demo.cpp @@ -0,0 +1,329 @@ +/* + * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <cstdio> +#include <cstring> +#include <unistd.h> +#include <service/crypto/client/cpp/crypto_client.h> +#include "ts-demo.h" + +class ts_demo { +public: + ts_demo(crypto_client *crypto_client, bool is_verbose) : + m_crypto_client(crypto_client), + m_signing_key_handle(0), + m_encryption_key_handle(0), + m_verbose(is_verbose), + m_all_ok(true) { + + } + + ~ts_demo() { + + } + + bool is_all_ok() const { + return m_all_ok; + } + + void print_intro() { + + 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 RPC call status %d\n", + status, m_crypto_client->err_rpc_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"); + } + + void generate_signing_key() + { + psa_status_t status; + 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_CURVE_SECP_R1)); + psa_set_key_bits(&attributes, 256); + + if (m_verbose) printf("Generating ECC signing key"); + + status = m_crypto_client->generate_key(&attributes, &m_signing_key_handle); + psa_reset_key_attributes(&attributes); + + print_status(status); + + m_all_ok &= (status == PSA_SUCCESS); + } + + void sign_and_verify_message(const char *message) + { + + psa_status_t status; + uint8_t hash[100]; + size_t hash_len = strlen(message) + 1; + + if (hash_len > sizeof(hash)) hash_len = sizeof(hash) - 1; + + memset(hash, 0, sizeof(hash)); + memcpy(hash, message, hash_len); + + /* Sign message */ + uint8_t signature[PSA_SIGNATURE_MAX_SIZE]; + size_t signature_length; + + if (m_verbose) printf("Signing message: \"%s\" using key: %d", hash, m_signing_key_handle); + + status = m_crypto_client->sign_hash(m_signing_key_handle, + PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256), hash, hash_len, + signature, sizeof(signature), &signature_length); + + print_status(status); + + if (m_verbose && (status == PSA_SUCCESS)) { + printf("\tSignature bytes: "); + print_byte_array(signature, signature_length); + } + + m_all_ok &= (status == PSA_SUCCESS); + + /* Verify signature against original message */ + if (m_verbose) printf("Verify signature using original message: \"%s\"", hash); + + status = m_crypto_client->verify_hash(m_signing_key_handle, + PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256), hash, hash_len, + signature, signature_length); + + print_status(status); + + m_all_ok &= (status == PSA_SUCCESS); + + /* Verify signature against modified message */ + hash[0] = '!'; + if (m_verbose) printf("Verify signature using modified message: \"%s\"", hash); + + status = m_crypto_client->verify_hash(m_signing_key_handle, + PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256), hash, hash_len, + signature, signature_length); + + if (status == PSA_ERROR_INVALID_SIGNATURE) { + if (m_verbose) printf("\n\tSuccessfully detected modified message\n"); + } + else { + print_status(status); + } + + m_all_ok &= (status != PSA_SUCCESS); + } + + void generate_asymmetric_encryption_key() + { + psa_status_t status; + 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, 256); + + if (m_verbose) printf("Generating RSA encryption key"); + + status = m_crypto_client->generate_key(&attributes, &m_encryption_key_handle); + psa_reset_key_attributes(&attributes); + + print_status(status); + + m_all_ok &= (status == PSA_SUCCESS); + } + + void encrypt_add_decrypt_message(const char *message) + { + psa_status_t status; + size_t message_len = strlen(message) + 1; + + /* Encrypt a message */ + if (m_verbose) printf("Encrypting message: \"%s\" using RSA key: %d", message, m_encryption_key_handle); + + uint8_t ciphertext[256]; + size_t ciphertext_len = 0; + + status = m_crypto_client->asymmetric_encrypt(m_encryption_key_handle, 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); + } + + m_all_ok &= (status == PSA_SUCCESS); + + /* Decrypt it */ + if (m_verbose) printf("Decrypting message using RSA key: %d", m_encryption_key_handle); + + uint8_t plaintext[256]; + size_t plaintext_len = 0; + + status = m_crypto_client->asymmetric_decrypt(m_encryption_key_handle, 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)) { + if (m_verbose) printf("\tDecrypted message: \"%s\"\n", plaintext); + } + else { + printf("\tDecrypted message is different from original!: "); + print_byte_array(plaintext, plaintext_len); + } + } + + m_all_ok &= (status == PSA_SUCCESS); + } + + void export_public_key() + { + psa_status_t status; + uint8_t key_buf[PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(256)]; + size_t key_len = 0; + + if (m_verbose) printf("Exporting public key: %d", m_signing_key_handle); + + status = m_crypto_client->export_public_key(m_signing_key_handle, 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); + } + + m_all_ok &= (status == PSA_SUCCESS); + } + + void generate_random_number(size_t length) + { + psa_status_t status; + uint8_t buffer[length]; + + if (m_verbose) printf("Generating random bytes length: %ld", length); + + status = m_crypto_client->generate_random(buffer, length); + + print_status(status); + + if (m_verbose && (status == PSA_SUCCESS)) { + printf("\tRandom bytes: "); + print_byte_array(buffer, length); + } + + m_all_ok &= (status == PSA_SUCCESS); + } + + void destroy_keys() + { + psa_status_t status; + + if (m_verbose) printf("Destroying signing key: %d", m_signing_key_handle); + status = m_crypto_client->destroy_key(m_signing_key_handle); + print_status(status); + m_all_ok &= (status == PSA_SUCCESS); + + if (m_verbose) printf("Destroying encryption key: %d", m_encryption_key_handle); + status = m_crypto_client->destroy_key(m_encryption_key_handle); + print_status(status); + m_all_ok &= (status == PSA_SUCCESS); + } + +private: + + static const psa_key_id_t SIGNING_KEY_ID = 0x100; + static const psa_key_id_t ENCRYPTION_KEY_ID = 0x101; + + crypto_client *m_crypto_client; + psa_key_handle_t m_signing_key_handle; + psa_key_handle_t m_encryption_key_handle; + + bool m_verbose; + bool m_all_ok; +}; + + +int run_ts_demo(crypto_client *crypto_client, bool is_verbose) { + + ts_demo demo(crypto_client, is_verbose); + + demo.print_intro(); + demo.wait(1); + demo.generate_random_number(1); + demo.wait(1); + demo.generate_random_number(7); + demo.wait(1); + demo.generate_random_number(128); + demo.wait(1); + demo.generate_signing_key(); + demo.wait(2); + demo.sign_and_verify_message("The quick brown fox"); + demo.wait(3); + demo.sign_and_verify_message("jumps over the lazy dog"); + demo.wait(3); + demo.generate_asymmetric_encryption_key(); + demo.wait(2); + demo.encrypt_add_decrypt_message("Top secret"); + demo.wait(3); + demo.export_public_key(); + demo.wait(2); + demo.destroy_keys(); + demo.wait(2); + + return demo.is_all_ok() ? 0 : -1; +} |