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