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