1 /* Copyright (c) 2024 Nordic Semiconductor
2 * SPDX-License-Identifier: Apache-2.0
3 */
4 #include <psa/crypto.h>
5 #include <zephyr/logging/log.h>
6 #include <zephyr/psa/key_ids.h>
7
8 LOG_MODULE_REGISTER(persistent_key);
9
10 #define SAMPLE_KEY_ID ZEPHYR_PSA_APPLICATION_KEY_ID_RANGE_BEGIN
11 #define SAMPLE_KEY_TYPE PSA_KEY_TYPE_AES
12 #define SAMPLE_ALG PSA_ALG_CTR
13 #define SAMPLE_KEY_BITS 256
14
generate_persistent_key(void)15 int generate_persistent_key(void)
16 {
17 LOG_INF("Generating a persistent key...");
18 psa_status_t ret;
19 psa_key_id_t key_id;
20 psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
21
22 psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_PERSISTENT);
23 psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
24 psa_set_key_id(&key_attributes, SAMPLE_KEY_ID);
25 psa_set_key_type(&key_attributes, SAMPLE_KEY_TYPE);
26 psa_set_key_algorithm(&key_attributes, SAMPLE_ALG);
27 psa_set_key_bits(&key_attributes, SAMPLE_KEY_BITS);
28
29 ret = psa_generate_key(&key_attributes, &key_id);
30 if (ret != PSA_SUCCESS) {
31 LOG_ERR("Failed to generate the key. (%d)", ret);
32 return -1;
33 }
34 __ASSERT_NO_MSG(key_id == SAMPLE_KEY_ID);
35
36 /* Purge the key from volatile memory. Has the same affect than resetting the device. */
37 ret = psa_purge_key(SAMPLE_KEY_ID);
38 if (ret != PSA_SUCCESS) {
39 LOG_ERR("Failed to purge the generated key from volatile memory. (%d).", ret);
40 return -1;
41 }
42
43 LOG_INF("Persistent key generated.");
44 return 0;
45 }
46
use_persistent_key(void)47 int use_persistent_key(void)
48 {
49 LOG_INF("Using the persistent key to encrypt and decrypt some plaintext...");
50 psa_status_t ret;
51 size_t ciphertext_len;
52 size_t decrypted_text_len;
53
54 static uint8_t plaintext[] =
55 "Example plaintext to demonstrate basic usage of a persistent key.";
56 static uint8_t ciphertext[PSA_CIPHER_ENCRYPT_OUTPUT_SIZE(SAMPLE_KEY_TYPE, SAMPLE_ALG,
57 sizeof(plaintext))];
58 static uint8_t decrypted_text[sizeof(plaintext)];
59
60 ret = psa_cipher_encrypt(SAMPLE_KEY_ID, SAMPLE_ALG, plaintext, sizeof(plaintext),
61 ciphertext, sizeof(ciphertext), &ciphertext_len);
62 if (ret != PSA_SUCCESS) {
63 LOG_ERR("Failed to encrypt the plaintext. (%d)", ret);
64 return -1;
65 }
66
67 ret = psa_cipher_decrypt(SAMPLE_KEY_ID, SAMPLE_ALG, ciphertext, ciphertext_len,
68 decrypted_text, sizeof(decrypted_text), &decrypted_text_len);
69 if (ret != PSA_SUCCESS) {
70 LOG_ERR("Failed to decrypt the ciphertext. (%d)", ret);
71 return -1;
72 }
73 __ASSERT_NO_MSG(decrypted_text_len == sizeof(plaintext));
74
75 /* Make sure the decryption gives us the original plaintext back. */
76 if (memcmp(plaintext, decrypted_text, sizeof(plaintext))) {
77 LOG_HEXDUMP_INF(plaintext, sizeof(plaintext), "Plaintext:");
78 LOG_HEXDUMP_INF(ciphertext, ciphertext_len, "Ciphertext:");
79 LOG_HEXDUMP_INF(decrypted_text, sizeof(decrypted_text), "Decrypted text:");
80 LOG_ERR("The decrypted text doesn't match the plaintext.");
81 return -1;
82 }
83
84 LOG_INF("Persistent key usage successful.");
85 return 0;
86 }
87
destroy_persistent_key(void)88 static int destroy_persistent_key(void)
89 {
90 LOG_INF("Destroying the persistent key...");
91 psa_status_t ret;
92
93 ret = psa_destroy_key(SAMPLE_KEY_ID);
94 if (ret != PSA_SUCCESS) {
95 LOG_ERR("Failed to destroy the key. (%d)", ret);
96 return -1;
97 }
98
99 LOG_INF("Persistent key destroyed.");
100 return 0;
101 }
102
main(void)103 int main(void)
104 {
105 LOG_INF("Persistent key sample started.");
106
107 /* Ensure there is not already a key with this ID. */
108 psa_destroy_key(SAMPLE_KEY_ID);
109
110 if (generate_persistent_key()) {
111 return -1;
112 }
113
114 if (use_persistent_key()) {
115 return -1;
116 }
117
118 if (destroy_persistent_key()) {
119 return -1;
120 }
121
122 LOG_INF("Sample finished successfully.");
123 return 0;
124 }
125