blob: 858e0ed0749dd8e0ab0144180028bf87825b8887 [file] [log] [blame] [view]
Dave Rodgman38699e52023-01-20 12:43:53 +00001## Getting started with Mbed TLS
mohammad160387a7eeb2018-11-01 11:25:49 +02002
Dave Rodgman38699e52023-01-20 12:43:53 +00003### What is Mbed TLS?
mohammad160387a7eeb2018-11-01 11:25:49 +02004
Dave Rodgman38699e52023-01-20 12:43:53 +00005Mbed TLS is an open source cryptographic library that supports a wide range of
6cryptographic operations, including:
mohammad160387a7eeb2018-11-01 11:25:49 +02007* Key management
8* Hashing
9* Symmetric cryptography
10* Asymmetric cryptography
11* Message authentication (MAC)
12* Key generation and derivation
13* Authenticated encryption with associated data (AEAD)
14
Dave Rodgman38699e52023-01-20 12:43:53 +000015Mbed TLS provides a reference implementation of the cryptography interface of
16the Arm Platform Security Architecture (PSA). It is written in portable C.
mohammad160387a7eeb2018-11-01 11:25:49 +020017
Dave Rodgman38699e52023-01-20 12:43:53 +000018Mbed TLS is distributed under the Apache License, version 2.0.
mohammad160387a7eeb2018-11-01 11:25:49 +020019
20#### Platform Security Architecture (PSA)
21
22Arm's Platform Security Architecture (PSA) is a holistic set of threat models,
Dave Rodgman38699e52023-01-20 12:43:53 +000023security analyses, hardware and firmware architecture specifications, and an open
24source firmware reference implementation. PSA provides a recipe, based on
25industry best practice, that enables you to design security into both hardware
26and firmware consistently. Part of the API provided by PSA is the cryptography
27interface, which provides access to a set of primitives.
mohammad160387a7eeb2018-11-01 11:25:49 +020028
Dave Rodgman38699e52023-01-20 12:43:53 +000029### Using Mbed TLS
mohammad160387a7eeb2018-11-01 11:25:49 +020030
Dave Rodgman38699e52023-01-20 12:43:53 +000031* [Getting the Mbed TLS library](#getting-the-mbed-tls-library)
32* [Building the Mbed TLS library](#building-the-mbed-tls-library)
33* [Using the PSA Crypto API](#using-the-psa-crypto-api)
mohammad160387a7eeb2018-11-01 11:25:49 +020034* [Importing a key](#importing-a-key)
35* [Signing a message using RSA](#signing-a-message-using-RSA)
36* [Encrypting or decrypting using symmetric ciphers](#encrypting-or-decrypting-using-symmetric-ciphers)
37* [Hashing a message](#hashing-a-message)
38* [Deriving a new key from an existing key](#deriving-a-new-key-from-an-existing-key)
39* [Generating a random value](#generating-a-random-value)
40* [Authenticating and encrypting or decrypting a message](#authenticating-and-encrypting-or-decrypting-a-message)
41* [Generating and exporting keys](#generating-and-exporting-keys)
Dave Rodgman38699e52023-01-20 12:43:53 +000042* [More about the Mbed TLS library](#more-about-the-psa-crypto-api)
mohammad160387a7eeb2018-11-01 11:25:49 +020043
Dave Rodgman38699e52023-01-20 12:43:53 +000044### Getting the Mbed TLS library
mohammad160387a7eeb2018-11-01 11:25:49 +020045
Dave Rodgman38699e52023-01-20 12:43:53 +000046Mbed TLS releases are available in the [public GitHub repository](https://github.com/Mbed-TLS/mbedtls).
mohammad160387a7eeb2018-11-01 11:25:49 +020047
Dave Rodgman38699e52023-01-20 12:43:53 +000048### Building the Mbed TLS library
mohammad160387a7eeb2018-11-01 11:25:49 +020049
Guy Wildc03c0fc2019-09-03 13:18:04 +030050**Prerequisites to building the library with the provided makefiles:**
mohammad160387a7eeb2018-11-01 11:25:49 +020051* GNU Make.
Dave Rodgman38699e52023-01-20 12:43:53 +000052* A C toolchain (compiler, linker, archiver) that supports C99.
53* Python 3.6 to generate the test code.
mohammad160387a7eeb2018-11-01 11:25:49 +020054* Perl to run the tests.
55
Dave Rodgman38699e52023-01-20 12:43:53 +000056If you have a C compiler such as GCC or Clang, just run `make` in the top-level
57directory to build the library, a set of unit tests and some sample programs.
mohammad160387a7eeb2018-11-01 11:25:49 +020058
Dave Rodgman38699e52023-01-20 12:43:53 +000059To select a different compiler, set the `CC` variable to the name or path of the
60compiler and linker (default: `cc`) and set `AR` to a compatible archiver
61(default: `ar`); for example:
mohammad160387a7eeb2018-11-01 11:25:49 +020062```
63make CC=arm-linux-gnueabi-gcc AR=arm-linux-gnueabi-ar
64```
Dave Rodgman38699e52023-01-20 12:43:53 +000065The provided makefiles pass options to the compiler that assume a GCC-like
66command line syntax. To use a different compiler, you may need to pass different
67values for `CFLAGS`, `WARNINGS_CFLAGS` and `LDFLAGS`.
mohammad160387a7eeb2018-11-01 11:25:49 +020068
Dave Rodgman38699e52023-01-20 12:43:53 +000069To run the unit tests on the host machine, run `make test` from the top-level
70directory. If you are cross-compiling, copy the test executable from the `tests`
71directory to the target machine.
mohammad160387a7eeb2018-11-01 11:25:49 +020072
Dave Rodgman38699e52023-01-20 12:43:53 +000073### Using the PSA Crypto API
mohammad160387a7eeb2018-11-01 11:25:49 +020074
Dave Rodgman38699e52023-01-20 12:43:53 +000075To use the PSA APIs, call `psa_crypto_init()` before calling any other PSA API.
76This initializes the library.
mohammad160387a7eeb2018-11-01 11:25:49 +020077
78### Importing a key
79
Dave Rodgman38699e52023-01-20 12:43:53 +000080To use a key for cryptography operations in PSA, you need to first
Ronald Croncf56a0a2020-08-04 09:51:30 +020081import it. The import operation returns the identifier of the key for use
Jaeden Amero884738a2019-08-16 17:58:31 +010082with other function calls.
mohammad160387a7eeb2018-11-01 11:25:49 +020083
Guy Wild802b19f2019-09-03 16:40:44 +030084**Prerequisites to importing keys:**
Guy Wildc03c0fc2019-09-03 13:18:04 +030085* Initialize the library with a successful call to `psa_crypto_init()`.
mohammad160387a7eeb2018-11-01 11:25:49 +020086
Guy Wildc03c0fc2019-09-03 13:18:04 +030087This example shows how to import a key:
mohammad160387a7eeb2018-11-01 11:25:49 +020088```C
Jaeden Amerofbdf1502019-11-08 09:59:16 +000089void import_a_key(const uint8_t *key, size_t key_len)
90{
Jaeden Amero884738a2019-08-16 17:58:31 +010091 psa_status_t status;
92 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
Andrzej Kureke3ed8242021-11-19 13:40:20 +010093 psa_key_id_t key_id;
mohammad160387a7eeb2018-11-01 11:25:49 +020094
Jaeden Amero884738a2019-08-16 17:58:31 +010095 printf("Import an AES key...\t");
96 fflush(stdout);
97
98 /* Initialize PSA Crypto */
99 status = psa_crypto_init();
100 if (status != PSA_SUCCESS) {
101 printf("Failed to initialize PSA Crypto\n");
102 return;
103 }
104
105 /* Set key attributes */
106 psa_set_key_usage_flags(&attributes, 0);
107 psa_set_key_algorithm(&attributes, 0);
108 psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
109 psa_set_key_bits(&attributes, 128);
mohammad160387a7eeb2018-11-01 11:25:49 +0200110
111 /* Import the key */
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100112 status = psa_import_key(&attributes, key, key_len, &key_id);
Jaeden Amero884738a2019-08-16 17:58:31 +0100113 if (status != PSA_SUCCESS) {
114 printf("Failed to import key\n");
115 return;
116 }
117 printf("Imported a key\n");
mohammad160387a7eeb2018-11-01 11:25:49 +0200118
Jaeden Amero884738a2019-08-16 17:58:31 +0100119 /* Free the attributes */
120 psa_reset_key_attributes(&attributes);
mohammad160387a7eeb2018-11-01 11:25:49 +0200121
122 /* Destroy the key */
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100123 psa_destroy_key(key_id);
Jaeden Amero884738a2019-08-16 17:58:31 +0100124
mohammad160387a7eeb2018-11-01 11:25:49 +0200125 mbedtls_psa_crypto_free();
Jaeden Amerofbdf1502019-11-08 09:59:16 +0000126}
mohammad160387a7eeb2018-11-01 11:25:49 +0200127```
128
129### Signing a message using RSA
130
Dave Rodgman38699e52023-01-20 12:43:53 +0000131The PSA Crypto API supports encrypting, decrypting, signing and verifying
132messages using public key signature algorithms, such as RSA or ECDSA.
mohammad160387a7eeb2018-11-01 11:25:49 +0200133
Guy Wildc03c0fc2019-09-03 13:18:04 +0300134**Prerequisites to performing asymmetric signature operations:**
135* Initialize the library with a successful call to `psa_crypto_init()`.
Jaeden Amero884738a2019-08-16 17:58:31 +0100136* Have a valid key with appropriate attributes set:
Gilles Peskine89d8c5c2019-11-26 17:01:59 +0100137 * Usage flag `PSA_KEY_USAGE_SIGN_HASH` to allow signing.
138 * Usage flag `PSA_KEY_USAGE_VERIFY_HASH` to allow signature verification.
Guy Wildc03c0fc2019-09-03 13:18:04 +0300139 * Algorithm set to the desired signature algorithm.
mohammad160387a7eeb2018-11-01 11:25:49 +0200140
Guy Wild5033fdd2019-09-04 09:14:55 +0300141This example shows how to sign a hash that has already been calculated:
mohammad160387a7eeb2018-11-01 11:25:49 +0200142```C
Jaeden Amerofbdf1502019-11-08 09:59:16 +0000143void sign_a_message_using_rsa(const uint8_t *key, size_t key_len)
144{
mohammad160387a7eeb2018-11-01 11:25:49 +0200145 psa_status_t status;
Jaeden Amero884738a2019-08-16 17:58:31 +0100146 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
Guy Wild5033fdd2019-09-04 09:14:55 +0300147 uint8_t hash[32] = {0x50, 0xd8, 0x58, 0xe0, 0x98, 0x5e, 0xcc, 0x7f,
Guy Wild5b1347a2019-09-05 09:46:31 +0300148 0x60, 0x41, 0x8a, 0xaf, 0x0c, 0xc5, 0xab, 0x58,
149 0x7f, 0x42, 0xc2, 0x57, 0x0a, 0x88, 0x40, 0x95,
150 0xa9, 0xe8, 0xcc, 0xac, 0xd0, 0xf6, 0x54, 0x5c};
Gilles Peskine89d8c5c2019-11-26 17:01:59 +0100151 uint8_t signature[PSA_SIGNATURE_MAX_SIZE] = {0};
mohammad160387a7eeb2018-11-01 11:25:49 +0200152 size_t signature_length;
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100153 psa_key_id_t key_id;
mohammad160387a7eeb2018-11-01 11:25:49 +0200154
Jaeden Amero884738a2019-08-16 17:58:31 +0100155 printf("Sign a message...\t");
156 fflush(stdout);
157
158 /* Initialize PSA Crypto */
mohammad160387a7eeb2018-11-01 11:25:49 +0200159 status = psa_crypto_init();
Jaeden Amero884738a2019-08-16 17:58:31 +0100160 if (status != PSA_SUCCESS) {
161 printf("Failed to initialize PSA Crypto\n");
162 return;
163 }
164
165 /* Set key attributes */
Gilles Peskine89d8c5c2019-11-26 17:01:59 +0100166 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);
Jaeden Amero884738a2019-08-16 17:58:31 +0100167 psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_SIGN_RAW);
168 psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR);
169 psa_set_key_bits(&attributes, 1024);
mohammad160387a7eeb2018-11-01 11:25:49 +0200170
171 /* Import the key */
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100172 status = psa_import_key(&attributes, key, key_len, &key_id);
Jaeden Amero884738a2019-08-16 17:58:31 +0100173 if (status != PSA_SUCCESS) {
174 printf("Failed to import key\n");
175 return;
176 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200177
Jaeden Amero884738a2019-08-16 17:58:31 +0100178 /* Sign message using the key */
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100179 status = psa_sign_hash(key_id, PSA_ALG_RSA_PKCS1V15_SIGN_RAW,
Gilles Peskine89d8c5c2019-11-26 17:01:59 +0100180 hash, sizeof(hash),
181 signature, sizeof(signature),
182 &signature_length);
Jaeden Amero884738a2019-08-16 17:58:31 +0100183 if (status != PSA_SUCCESS) {
184 printf("Failed to sign\n");
185 return;
186 }
187
188 printf("Signed a message\n");
189
190 /* Free the attributes */
191 psa_reset_key_attributes(&attributes);
192
mohammad160387a7eeb2018-11-01 11:25:49 +0200193 /* Destroy the key */
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100194 psa_destroy_key(key_id);
Jaeden Amero884738a2019-08-16 17:58:31 +0100195
mohammad160387a7eeb2018-11-01 11:25:49 +0200196 mbedtls_psa_crypto_free();
Jaeden Amerofbdf1502019-11-08 09:59:16 +0000197}
mohammad160387a7eeb2018-11-01 11:25:49 +0200198```
199
Jaeden Amero884738a2019-08-16 17:58:31 +0100200### Using symmetric ciphers
mohammad160387a7eeb2018-11-01 11:25:49 +0200201
Dave Rodgman38699e52023-01-20 12:43:53 +0000202The PSA Crypto API supports encrypting and decrypting messages using various
203symmetric cipher algorithms (both block and stream ciphers).
mohammad160387a7eeb2018-11-01 11:25:49 +0200204
Guy Wildc03c0fc2019-09-03 13:18:04 +0300205**Prerequisites to working with the symmetric cipher API:**
206* Initialize the library with a successful call to `psa_crypto_init()`.
Dave Rodgman38699e52023-01-20 12:43:53 +0000207* Have a symmetric key. This key's usage flags must include `PSA_KEY_USAGE_ENCRYPT`
208 to allow encryption or `PSA_KEY_USAGE_DECRYPT` to allow decryption.
mohammad160387a7eeb2018-11-01 11:25:49 +0200209
Guy Wildc03c0fc2019-09-03 13:18:04 +0300210**To encrypt a message with a symmetric cipher:**
Dave Rodgman38699e52023-01-20 12:43:53 +00002111. Allocate an operation (`psa_cipher_operation_t`) structure to pass to the
212 cipher functions.
Guy Wild33d421d2019-09-04 09:16:14 +03002131. Initialize the operation structure to zero or to `PSA_CIPHER_OPERATION_INIT`.
Dave Rodgman38699e52023-01-20 12:43:53 +00002141. Call `psa_cipher_encrypt_setup()` to specify the algorithm and the key to be
215 used.
2161. Call either `psa_cipher_generate_iv()` or `psa_cipher_set_iv()` to generate
217 or set the initialization vector (IV). We recommend calling
218 `psa_cipher_generate_iv()`, unless you require a specific IV value.
2191. Call `psa_cipher_update()` with the message to encrypt. You may call this
220 function multiple times, passing successive fragments of the message on
221 successive calls.
2221. Call `psa_cipher_finish()` to end the operation and output the encrypted
223 message.
mohammad160387a7eeb2018-11-01 11:25:49 +0200224
Dave Rodgman38699e52023-01-20 12:43:53 +0000225This example shows how to encrypt data using an AES (Advanced Encryption
226Standard) key in CBC (Cipher Block Chaining) mode with no padding (assuming all
227prerequisites have been fulfilled):
mohammad160387a7eeb2018-11-01 11:25:49 +0200228```c
Jaeden Amerofbdf1502019-11-08 09:59:16 +0000229void encrypt_with_symmetric_ciphers(const uint8_t *key, size_t key_len)
230{
Jaeden Amero884738a2019-08-16 17:58:31 +0100231 enum {
gabor-mezei-armcbcec212020-12-18 14:23:51 +0100232 block_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH(PSA_KEY_TYPE_AES),
Jaeden Amero884738a2019-08-16 17:58:31 +0100233 };
234 psa_status_t status;
235 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
mohammad160387a7eeb2018-11-01 11:25:49 +0200236 psa_algorithm_t alg = PSA_ALG_CBC_NO_PADDING;
Jaeden Amero884738a2019-08-16 17:58:31 +0100237 uint8_t plaintext[block_size] = SOME_PLAINTEXT;
238 uint8_t iv[block_size];
mohammad160387a7eeb2018-11-01 11:25:49 +0200239 size_t iv_len;
Jaeden Amero884738a2019-08-16 17:58:31 +0100240 uint8_t output[block_size];
mohammad160387a7eeb2018-11-01 11:25:49 +0200241 size_t output_len;
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100242 psa_key_id_t key_id;
Jaeden Amero884738a2019-08-16 17:58:31 +0100243 psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
mohammad160387a7eeb2018-11-01 11:25:49 +0200244
Jaeden Amero884738a2019-08-16 17:58:31 +0100245 printf("Encrypt with cipher...\t");
246 fflush(stdout);
mohammad160387a7eeb2018-11-01 11:25:49 +0200247
Jaeden Amero884738a2019-08-16 17:58:31 +0100248 /* Initialize PSA Crypto */
249 status = psa_crypto_init();
250 if (status != PSA_SUCCESS)
251 {
252 printf("Failed to initialize PSA Crypto\n");
253 return;
254 }
255
256 /* Import a key */
257 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
258 psa_set_key_algorithm(&attributes, alg);
259 psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
260 psa_set_key_bits(&attributes, 128);
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100261 status = psa_import_key(&attributes, key, key_len, &key_id);
Jaeden Amero884738a2019-08-16 17:58:31 +0100262 if (status != PSA_SUCCESS) {
263 printf("Failed to import a key\n");
264 return;
265 }
266 psa_reset_key_attributes(&attributes);
267
268 /* Encrypt the plaintext */
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100269 status = psa_cipher_encrypt_setup(&operation, key_id, alg);
Jaeden Amero884738a2019-08-16 17:58:31 +0100270 if (status != PSA_SUCCESS) {
271 printf("Failed to begin cipher operation\n");
272 return;
273 }
274 status = psa_cipher_generate_iv(&operation, iv, sizeof(iv), &iv_len);
275 if (status != PSA_SUCCESS) {
276 printf("Failed to generate IV\n");
277 return;
278 }
279 status = psa_cipher_update(&operation, plaintext, sizeof(plaintext),
280 output, sizeof(output), &output_len);
281 if (status != PSA_SUCCESS) {
282 printf("Failed to update cipher operation\n");
283 return;
284 }
285 status = psa_cipher_finish(&operation, output + output_len,
286 sizeof(output) - output_len, &output_len);
287 if (status != PSA_SUCCESS) {
288 printf("Failed to finish cipher operation\n");
289 return;
290 }
291 printf("Encrypted plaintext\n");
292
mohammad160387a7eeb2018-11-01 11:25:49 +0200293 /* Clean up cipher operation context */
294 psa_cipher_abort(&operation);
Jaeden Amero884738a2019-08-16 17:58:31 +0100295
296 /* Destroy the key */
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100297 psa_destroy_key(key_id);
Jaeden Amero884738a2019-08-16 17:58:31 +0100298
299 mbedtls_psa_crypto_free();
Jaeden Amerofbdf1502019-11-08 09:59:16 +0000300}
mohammad160387a7eeb2018-11-01 11:25:49 +0200301```
302
Guy Wildc03c0fc2019-09-03 13:18:04 +0300303**To decrypt a message with a symmetric cipher:**
Dave Rodgman38699e52023-01-20 12:43:53 +00003041. Allocate an operation (`psa_cipher_operation_t`) structure to pass to the
305 cipher functions.
Guy Wild2a9e9f72019-09-04 13:45:54 +03003061. Initialize the operation structure to zero or to `PSA_CIPHER_OPERATION_INIT`.
Dave Rodgman38699e52023-01-20 12:43:53 +00003071. Call `psa_cipher_decrypt_setup()` to specify the algorithm and the key to be
308 used.
Guy Wildc03c0fc2019-09-03 13:18:04 +03003091. Call `psa_cipher_set_iv()` with the IV for the decryption.
Dave Rodgman38699e52023-01-20 12:43:53 +00003101. Call `psa_cipher_update()` with the message to encrypt. You may call this
311 function multiple times, passing successive fragments of the message on
312 successive calls.
3131. Call `psa_cipher_finish()` to end the operation and output the decrypted
314 message.
mohammad160387a7eeb2018-11-01 11:25:49 +0200315
Dave Rodgman38699e52023-01-20 12:43:53 +0000316This example shows how to decrypt encrypted data using an AES key in CBC mode
317with no padding (assuming all prerequisites have been fulfilled):
mohammad160387a7eeb2018-11-01 11:25:49 +0200318```c
Jaeden Amerofbdf1502019-11-08 09:59:16 +0000319void decrypt_with_symmetric_ciphers(const uint8_t *key, size_t key_len)
320{
Jaeden Amero884738a2019-08-16 17:58:31 +0100321 enum {
gabor-mezei-armcbcec212020-12-18 14:23:51 +0100322 block_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH(PSA_KEY_TYPE_AES),
Jaeden Amero884738a2019-08-16 17:58:31 +0100323 };
324 psa_status_t status;
325 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
mohammad160387a7eeb2018-11-01 11:25:49 +0200326 psa_algorithm_t alg = PSA_ALG_CBC_NO_PADDING;
Jaeden Amero884738a2019-08-16 17:58:31 +0100327 psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
328 uint8_t ciphertext[block_size] = SOME_CIPHERTEXT;
329 uint8_t iv[block_size] = ENCRYPTED_WITH_IV;
Jaeden Amero884738a2019-08-16 17:58:31 +0100330 uint8_t output[block_size];
mohammad160387a7eeb2018-11-01 11:25:49 +0200331 size_t output_len;
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100332 psa_key_id_t key_id;
mohammad160387a7eeb2018-11-01 11:25:49 +0200333
Jaeden Amero884738a2019-08-16 17:58:31 +0100334 printf("Decrypt with cipher...\t");
335 fflush(stdout);
mohammad160387a7eeb2018-11-01 11:25:49 +0200336
Jaeden Amero884738a2019-08-16 17:58:31 +0100337 /* Initialize PSA Crypto */
338 status = psa_crypto_init();
339 if (status != PSA_SUCCESS)
340 {
341 printf("Failed to initialize PSA Crypto\n");
342 return;
343 }
344
345 /* Import a key */
346 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT);
347 psa_set_key_algorithm(&attributes, alg);
348 psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
349 psa_set_key_bits(&attributes, 128);
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100350 status = psa_import_key(&attributes, key, key_len, &key_id);
Jaeden Amero884738a2019-08-16 17:58:31 +0100351 if (status != PSA_SUCCESS) {
352 printf("Failed to import a key\n");
353 return;
354 }
355 psa_reset_key_attributes(&attributes);
356
357 /* Decrypt the ciphertext */
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100358 status = psa_cipher_decrypt_setup(&operation, key_id, alg);
Jaeden Amero884738a2019-08-16 17:58:31 +0100359 if (status != PSA_SUCCESS) {
360 printf("Failed to begin cipher operation\n");
361 return;
362 }
363 status = psa_cipher_set_iv(&operation, iv, sizeof(iv));
364 if (status != PSA_SUCCESS) {
365 printf("Failed to set IV\n");
366 return;
367 }
368 status = psa_cipher_update(&operation, ciphertext, sizeof(ciphertext),
369 output, sizeof(output), &output_len);
370 if (status != PSA_SUCCESS) {
371 printf("Failed to update cipher operation\n");
372 return;
373 }
374 status = psa_cipher_finish(&operation, output + output_len,
375 sizeof(output) - output_len, &output_len);
376 if (status != PSA_SUCCESS) {
377 printf("Failed to finish cipher operation\n");
378 return;
379 }
380 printf("Decrypted ciphertext\n");
381
mohammad160387a7eeb2018-11-01 11:25:49 +0200382 /* Clean up cipher operation context */
383 psa_cipher_abort(&operation);
Jaeden Amero884738a2019-08-16 17:58:31 +0100384
385 /* Destroy the key */
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100386 psa_destroy_key(key_id);
Jaeden Amero884738a2019-08-16 17:58:31 +0100387
388 mbedtls_psa_crypto_free();
Jaeden Amerofbdf1502019-11-08 09:59:16 +0000389}
mohammad160387a7eeb2018-11-01 11:25:49 +0200390```
391
392#### Handling cipher operation contexts
393
Dave Rodgman38699e52023-01-20 12:43:53 +0000394After you've initialized the operation structure with a successful call to
395`psa_cipher_encrypt_setup()` or `psa_cipher_decrypt_setup()`, you can terminate
396the operation at any time by calling `psa_cipher_abort()`.
mohammad160387a7eeb2018-11-01 11:25:49 +0200397
Dave Rodgman38699e52023-01-20 12:43:53 +0000398The call to `psa_cipher_abort()` frees any resources associated with the
399operation, except for the operation structure itself.
mohammad160387a7eeb2018-11-01 11:25:49 +0200400
Dave Rodgman38699e52023-01-20 12:43:53 +0000401The PSA Crypto API implicitly calls `psa_cipher_abort()` when:
402* A call to `psa_cipher_generate_iv()`, `psa_cipher_set_iv()` or
403 `psa_cipher_update()` fails (returning any status other than `PSA_SUCCESS`).
Guy Wildc03c0fc2019-09-03 13:18:04 +0300404* A call to `psa_cipher_finish()` succeeds or fails.
mohammad160387a7eeb2018-11-01 11:25:49 +0200405
Dave Rodgman38699e52023-01-20 12:43:53 +0000406After an implicit or explicit call to `psa_cipher_abort()`, the operation
407structure is invalidated; in other words, you cannot reuse the operation
408structure for the same operation. You can, however, reuse the operation
409structure for a different operation by calling either
410`psa_cipher_encrypt_setup()` or `psa_cipher_decrypt_setup()` again.
mohammad160387a7eeb2018-11-01 11:25:49 +0200411
Dave Rodgman38699e52023-01-20 12:43:53 +0000412You must call `psa_cipher_abort()` at some point for any operation that is
413initialized successfully (by a successful call to `psa_cipher_encrypt_setup()`
414or `psa_cipher_decrypt_setup()`).
Guy Wildc03c0fc2019-09-03 13:18:04 +0300415
Dave Rodgman38699e52023-01-20 12:43:53 +0000416Making multiple sequential calls to `psa_cipher_abort()` on an operation that
417is terminated (either implicitly or explicitly) is safe and has no effect.
mohammad160387a7eeb2018-11-01 11:25:49 +0200418
419### Hashing a message
420
Dave Rodgman38699e52023-01-20 12:43:53 +0000421The PSA Crypto API lets you compute and verify hashes using various hashing
Jaeden Amero884738a2019-08-16 17:58:31 +0100422algorithms.
mohammad160387a7eeb2018-11-01 11:25:49 +0200423
Guy Wildc03c0fc2019-09-03 13:18:04 +0300424**Prerequisites to working with the hash APIs:**
425* Initialize the library with a successful call to `psa_crypto_init()`.
mohammad160387a7eeb2018-11-01 11:25:49 +0200426
Guy Wildc03c0fc2019-09-03 13:18:04 +0300427**To calculate a hash:**
Dave Rodgman38699e52023-01-20 12:43:53 +00004281. Allocate an operation structure (`psa_hash_operation_t`) to pass to the hash
429 functions.
Guy Wildeefc5172019-09-04 09:16:53 +03004301. Initialize the operation structure to zero or to `PSA_HASH_OPERATION_INIT`.
4311. Call `psa_hash_setup()` to specify the hash algorithm.
Dave Rodgman38699e52023-01-20 12:43:53 +00004321. Call `psa_hash_update()` with the message to encrypt. You may call this
433 function multiple times, passing successive fragments of the message on
434 successive calls.
4351. Call `psa_hash_finish()` to calculate the hash, or `psa_hash_verify()` to
436 compare the computed hash with an expected hash value.
mohammad160387a7eeb2018-11-01 11:25:49 +0200437
Guy Wild2a9e9f72019-09-04 13:45:54 +0300438This example shows how to calculate the SHA-256 hash of a message:
mohammad160387a7eeb2018-11-01 11:25:49 +0200439```c
Jaeden Amero884738a2019-08-16 17:58:31 +0100440 psa_status_t status;
mohammad160387a7eeb2018-11-01 11:25:49 +0200441 psa_algorithm_t alg = PSA_ALG_SHA_256;
Jaeden Amero884738a2019-08-16 17:58:31 +0100442 psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
mohammad160387a7eeb2018-11-01 11:25:49 +0200443 unsigned char input[] = { 'a', 'b', 'c' };
444 unsigned char actual_hash[PSA_HASH_MAX_SIZE];
445 size_t actual_hash_len;
446
Jaeden Amero884738a2019-08-16 17:58:31 +0100447 printf("Hash a message...\t");
448 fflush(stdout);
449
450 /* Initialize PSA Crypto */
451 status = psa_crypto_init();
452 if (status != PSA_SUCCESS) {
453 printf("Failed to initialize PSA Crypto\n");
454 return;
455 }
456
mohammad160387a7eeb2018-11-01 11:25:49 +0200457 /* Compute hash of message */
Jaeden Amero884738a2019-08-16 17:58:31 +0100458 status = psa_hash_setup(&operation, alg);
459 if (status != PSA_SUCCESS) {
460 printf("Failed to begin hash operation\n");
461 return;
462 }
463 status = psa_hash_update(&operation, input, sizeof(input));
464 if (status != PSA_SUCCESS) {
465 printf("Failed to update hash operation\n");
466 return;
467 }
468 status = psa_hash_finish(&operation, actual_hash, sizeof(actual_hash),
469 &actual_hash_len);
470 if (status != PSA_SUCCESS) {
471 printf("Failed to finish hash operation\n");
472 return;
473 }
474
475 printf("Hashed a message\n");
mohammad160387a7eeb2018-11-01 11:25:49 +0200476
477 /* Clean up hash operation context */
478 psa_hash_abort(&operation);
Jaeden Amero884738a2019-08-16 17:58:31 +0100479
480 mbedtls_psa_crypto_free();
mohammad160387a7eeb2018-11-01 11:25:49 +0200481```
482
Guy Wild2a9e9f72019-09-04 13:45:54 +0300483This example shows how to verify the SHA-256 hash of a message:
mohammad160387a7eeb2018-11-01 11:25:49 +0200484```c
Jaeden Amero884738a2019-08-16 17:58:31 +0100485 psa_status_t status;
mohammad160387a7eeb2018-11-01 11:25:49 +0200486 psa_algorithm_t alg = PSA_ALG_SHA_256;
Jaeden Amero884738a2019-08-16 17:58:31 +0100487 psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
mohammad160387a7eeb2018-11-01 11:25:49 +0200488 unsigned char input[] = { 'a', 'b', 'c' };
489 unsigned char expected_hash[] = {
490 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, 0xde,
491 0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
492 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad
493 };
gabor-mezei-armcbcec212020-12-18 14:23:51 +0100494 size_t expected_hash_len = PSA_HASH_LENGTH(alg);
mohammad160387a7eeb2018-11-01 11:25:49 +0200495
Jaeden Amero884738a2019-08-16 17:58:31 +0100496 printf("Verify a hash...\t");
497 fflush(stdout);
498
499 /* Initialize PSA Crypto */
500 status = psa_crypto_init();
501 if (status != PSA_SUCCESS) {
502 printf("Failed to initialize PSA Crypto\n");
503 return;
504 }
505
mohammad160387a7eeb2018-11-01 11:25:49 +0200506 /* Verify message hash */
Jaeden Amero884738a2019-08-16 17:58:31 +0100507 status = psa_hash_setup(&operation, alg);
508 if (status != PSA_SUCCESS) {
509 printf("Failed to begin hash operation\n");
510 return;
511 }
512 status = psa_hash_update(&operation, input, sizeof(input));
513 if (status != PSA_SUCCESS) {
514 printf("Failed to update hash operation\n");
515 return;
516 }
517 status = psa_hash_verify(&operation, expected_hash, expected_hash_len);
518 if (status != PSA_SUCCESS) {
519 printf("Failed to verify hash\n");
520 return;
521 }
522
523 printf("Verified a hash\n");
524
525 /* Clean up hash operation context */
526 psa_hash_abort(&operation);
527
528 mbedtls_psa_crypto_free();
mohammad160387a7eeb2018-11-01 11:25:49 +0200529```
530
Dave Rodgman38699e52023-01-20 12:43:53 +0000531The API provides the macro `PSA_HASH_LENGTH`, which returns the expected hash
532length (in bytes) for the specified algorithm.
mohammad160387a7eeb2018-11-01 11:25:49 +0200533
534#### Handling hash operation contexts
535
Dave Rodgman38699e52023-01-20 12:43:53 +0000536After a successful call to `psa_hash_setup()`, you can terminate the operation
537at any time by calling `psa_hash_abort()`. The call to `psa_hash_abort()` frees
538any resources associated with the operation, except for the operation structure
539itself.
mohammad160387a7eeb2018-11-01 11:25:49 +0200540
Dave Rodgman38699e52023-01-20 12:43:53 +0000541The PSA Crypto API implicitly calls `psa_hash_abort()` when:
5421. A call to `psa_hash_update()` fails (returning any status other than
543 `PSA_SUCCESS`).
Guy Wildc03c0fc2019-09-03 13:18:04 +03005441. A call to `psa_hash_finish()` succeeds or fails.
5451. A call to `psa_hash_verify()` succeeds or fails.
mohammad160387a7eeb2018-11-01 11:25:49 +0200546
Dave Rodgman38699e52023-01-20 12:43:53 +0000547After an implicit or explicit call to `psa_hash_abort()`, the operation
548structure is invalidated; in other words, you cannot reuse the operation
549structure for the same operation. You can, however, reuse the operation
550structure for a different operation by calling `psa_hash_setup()` again.
mohammad160387a7eeb2018-11-01 11:25:49 +0200551
Dave Rodgman38699e52023-01-20 12:43:53 +0000552You must call `psa_hash_abort()` at some point for any operation that is
553initialized successfully (by a successful call to `psa_hash_setup()`) .
mohammad160387a7eeb2018-11-01 11:25:49 +0200554
Dave Rodgman38699e52023-01-20 12:43:53 +0000555Making multiple sequential calls to `psa_hash_abort()` on an operation that has
556already been terminated (either implicitly or explicitly) is safe and has no
557effect.
mohammad160387a7eeb2018-11-01 11:25:49 +0200558
559### Generating a random value
560
Dave Rodgman38699e52023-01-20 12:43:53 +0000561The PSA Crypto API can generate random data.
mohammad160387a7eeb2018-11-01 11:25:49 +0200562
Guy Wild802b19f2019-09-03 16:40:44 +0300563**Prerequisites to generating random data:**
Jaeden Amero884738a2019-08-16 17:58:31 +0100564* Initialize the library with a successful call to `psa_crypto_init()`.
mohammad160387a7eeb2018-11-01 11:25:49 +0200565
Dave Rodgman38699e52023-01-20 12:43:53 +0000566<span class="notes">**Note:** To generate a random key, use `psa_generate_key()`
567instead of `psa_generate_random()`.</span>
Guy Wild802b19f2019-09-03 16:40:44 +0300568
Dave Rodgman38699e52023-01-20 12:43:53 +0000569This example shows how to generate ten bytes of random data by calling
570`psa_generate_random()`:
mohammad160387a7eeb2018-11-01 11:25:49 +0200571```C
572 psa_status_t status;
573 uint8_t random[10] = { 0 };
mohammad160387a7eeb2018-11-01 11:25:49 +0200574
Jaeden Amero884738a2019-08-16 17:58:31 +0100575 printf("Generate random...\t");
576 fflush(stdout);
577
578 /* Initialize PSA Crypto */
579 status = psa_crypto_init();
580 if (status != PSA_SUCCESS) {
581 printf("Failed to initialize PSA Crypto\n");
582 return;
583 }
584
585 status = psa_generate_random(random, sizeof(random));
586 if (status != PSA_SUCCESS) {
587 printf("Failed to generate a random value\n");
588 return;
589 }
590
591 printf("Generated random data\n");
592
593 /* Clean up */
mohammad160387a7eeb2018-11-01 11:25:49 +0200594 mbedtls_psa_crypto_free();
595```
596
597### Deriving a new key from an existing key
598
Dave Rodgman38699e52023-01-20 12:43:53 +0000599The PSA Crypto API provides a key derivation API that lets you derive new keys
600from existing ones. The key derivation API has functions to take inputs,
601including other keys and data, and functions to generate outputs, such as
602new keys or other data.
mohammad160387a7eeb2018-11-01 11:25:49 +0200603
Guy Wildc03c0fc2019-09-03 13:18:04 +0300604You must first initialize and set up a key derivation context,
Dave Rodgman38699e52023-01-20 12:43:53 +0000605provided with a key and, optionally, other data. Then, use the key derivation context
606to either read derived data to a buffer or send derived data directly to a key slot.
Guy Wildc03c0fc2019-09-03 13:18:04 +0300607
608See the documentation for the particular algorithm (such as HKDF or the TLS1.2 PRF) for
609information about which inputs to pass when, and when you can obtain which outputs.
610
611**Prerequisites to working with the key derivation APIs:**
612* Initialize the library with a successful call to `psa_crypto_init()`.
Jaeden Amero884738a2019-08-16 17:58:31 +0100613* Use a key with the appropriate attributes set:
614 * Usage flags set for key derivation (`PSA_KEY_USAGE_DERIVE`)
615 * Key type set to `PSA_KEY_TYPE_DERIVE`.
616 * Algorithm set to a key derivation algorithm
Guy Wild2a9e9f72019-09-04 13:45:54 +0300617 (for example, `PSA_ALG_HKDF(PSA_ALG_SHA_256)`).
mohammad160387a7eeb2018-11-01 11:25:49 +0200618
Guy Wildc03c0fc2019-09-03 13:18:04 +0300619**To derive a new AES-CTR 128-bit encryption key into a given key slot using HKDF
Guy Wild2a9e9f72019-09-04 13:45:54 +0300620with a given key, salt and info:**
Guy Wildc03c0fc2019-09-03 13:18:04 +0300621
6221. Set up the key derivation context using the `psa_key_derivation_setup()`
Jaeden Amero884738a2019-08-16 17:58:31 +0100623function, specifying the derivation algorithm `PSA_ALG_HKDF(PSA_ALG_SHA_256)`.
Guy Wild29008112019-09-05 11:38:14 +03006241. Provide an optional salt with `psa_key_derivation_input_bytes()`.
6251. Provide info with `psa_key_derivation_input_bytes()`.
6261. Provide a secret with `psa_key_derivation_input_key()`, referencing a key that
Jaeden Amero884738a2019-08-16 17:58:31 +0100627 can be used for key derivation.
6281. Set the key attributes desired for the new derived key. We'll set
Guy Wild0058ab62019-09-04 09:17:54 +0300629 the `PSA_KEY_USAGE_ENCRYPT` usage flag and the `PSA_ALG_CTR` algorithm for this
Jaeden Amero884738a2019-08-16 17:58:31 +0100630 example.
6311. Derive the key by calling `psa_key_derivation_output_key()`.
6321. Clean up the key derivation context.
mohammad160387a7eeb2018-11-01 11:25:49 +0200633
Guy Wildc03c0fc2019-09-03 13:18:04 +0300634At this point, the derived key slot holds a new 128-bit AES-CTR encryption key
Guy Wildce560772019-09-05 11:35:16 +0300635derived from the key, salt and info provided:
mohammad160387a7eeb2018-11-01 11:25:49 +0200636```C
Jaeden Amero884738a2019-08-16 17:58:31 +0100637 psa_status_t status;
638 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
639 static const unsigned char key[] = {
mohammad160387a7eeb2018-11-01 11:25:49 +0200640 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
641 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
642 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
643 0x0b };
Jaeden Amero884738a2019-08-16 17:58:31 +0100644 static const unsigned char salt[] = {
645 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
646 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c };
647 static const unsigned char info[] = {
648 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6,
649 0xf7, 0xf8, 0xf9 };
mohammad160387a7eeb2018-11-01 11:25:49 +0200650 psa_algorithm_t alg = PSA_ALG_HKDF(PSA_ALG_SHA_256);
Jaeden Amero884738a2019-08-16 17:58:31 +0100651 psa_key_derivation_operation_t operation =
652 PSA_KEY_DERIVATION_OPERATION_INIT;
mohammad160387a7eeb2018-11-01 11:25:49 +0200653 size_t derived_bits = 128;
654 size_t capacity = PSA_BITS_TO_BYTES(derived_bits);
Ronald Croncf56a0a2020-08-04 09:51:30 +0200655 psa_key_id_t base_key;
656 psa_key_id_t derived_key;
mohammad160387a7eeb2018-11-01 11:25:49 +0200657
Jaeden Amero884738a2019-08-16 17:58:31 +0100658 printf("Derive a key (HKDF)...\t");
659 fflush(stdout);
660
661 /* Initialize PSA Crypto */
mohammad160387a7eeb2018-11-01 11:25:49 +0200662 status = psa_crypto_init();
Jaeden Amero884738a2019-08-16 17:58:31 +0100663 if (status != PSA_SUCCESS) {
664 printf("Failed to initialize PSA Crypto\n");
665 return;
666 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200667
Jaeden Amero884738a2019-08-16 17:58:31 +0100668 /* Import a key for use in key derivation. If such a key has already been
669 * generated or imported, you can skip this part. */
670 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE);
671 psa_set_key_algorithm(&attributes, alg);
672 psa_set_key_type(&attributes, PSA_KEY_TYPE_DERIVE);
673 status = psa_import_key(&attributes, key, sizeof(key), &base_key);
674 if (status != PSA_SUCCESS) {
675 printf("Failed to import a key\n");
676 return;
677 }
678 psa_reset_key_attributes(&attributes);
mohammad160387a7eeb2018-11-01 11:25:49 +0200679
Jaeden Amero884738a2019-08-16 17:58:31 +0100680 /* Derive a key */
681 status = psa_key_derivation_setup(&operation, alg);
682 if (status != PSA_SUCCESS) {
683 printf("Failed to begin key derivation\n");
684 return;
685 }
686 status = psa_key_derivation_set_capacity(&operation, capacity);
687 if (status != PSA_SUCCESS) {
688 printf("Failed to set capacity\n");
689 return;
690 }
691 status = psa_key_derivation_input_bytes(&operation,
692 PSA_KEY_DERIVATION_INPUT_SALT,
693 salt, sizeof(salt));
694 if (status != PSA_SUCCESS) {
695 printf("Failed to input salt (extract)\n");
696 return;
697 }
698 status = psa_key_derivation_input_key(&operation,
699 PSA_KEY_DERIVATION_INPUT_SECRET,
700 base_key);
701 if (status != PSA_SUCCESS) {
702 printf("Failed to input key (extract)\n");
703 return;
704 }
705 status = psa_key_derivation_input_bytes(&operation,
706 PSA_KEY_DERIVATION_INPUT_INFO,
707 info, sizeof(info));
708 if (status != PSA_SUCCESS) {
709 printf("Failed to input info (expand)\n");
710 return;
711 }
712 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
713 psa_set_key_algorithm(&attributes, PSA_ALG_CTR);
714 psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
715 psa_set_key_bits(&attributes, 128);
716 status = psa_key_derivation_output_key(&attributes, &operation,
717 &derived_key);
718 if (status != PSA_SUCCESS) {
719 printf("Failed to derive key\n");
720 return;
721 }
722 psa_reset_key_attributes(&attributes);
mohammad160387a7eeb2018-11-01 11:25:49 +0200723
Jaeden Amero884738a2019-08-16 17:58:31 +0100724 printf("Derived key\n");
mohammad160387a7eeb2018-11-01 11:25:49 +0200725
Jaeden Amero884738a2019-08-16 17:58:31 +0100726 /* Clean up key derivation operation */
727 psa_key_derivation_abort(&operation);
mohammad160387a7eeb2018-11-01 11:25:49 +0200728
Jaeden Amero884738a2019-08-16 17:58:31 +0100729 /* Destroy the keys */
730 psa_destroy_key(derived_key);
731 psa_destroy_key(base_key);
mohammad160387a7eeb2018-11-01 11:25:49 +0200732
mohammad160387a7eeb2018-11-01 11:25:49 +0200733 mbedtls_psa_crypto_free();
734```
735
736### Authenticating and encrypting or decrypting a message
737
Dave Rodgman38699e52023-01-20 12:43:53 +0000738The PSA Crypto API provides a simple way to authenticate and encrypt with
739associated data (AEAD), supporting the `PSA_ALG_CCM` algorithm.
mohammad160387a7eeb2018-11-01 11:25:49 +0200740
Guy Wildc03c0fc2019-09-03 13:18:04 +0300741**Prerequisites to working with the AEAD cipher APIs:**
742* Initialize the library with a successful call to `psa_crypto_init()`.
Dave Rodgman38699e52023-01-20 12:43:53 +0000743* The key attributes for the key used for derivation must have the
744 `PSA_KEY_USAGE_ENCRYPT` or `PSA_KEY_USAGE_DECRYPT` usage flags.
mohammad160387a7eeb2018-11-01 11:25:49 +0200745
Guy Wildc03c0fc2019-09-03 13:18:04 +0300746This example shows how to authenticate and encrypt a message:
mohammad160387a7eeb2018-11-01 11:25:49 +0200747```C
mohammad160387a7eeb2018-11-01 11:25:49 +0200748 psa_status_t status;
Jaeden Amero884738a2019-08-16 17:58:31 +0100749 static const uint8_t key[] = {
750 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
751 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF };
752 static const uint8_t nonce[] = {
753 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
754 0x08, 0x09, 0x0A, 0x0B };
755 static const uint8_t additional_data[] = {
756 0xEC, 0x46, 0xBB, 0x63, 0xB0, 0x25,
757 0x20, 0xC3, 0x3C, 0x49, 0xFD, 0x70 };
758 static const uint8_t input_data[] = {
759 0xB9, 0x6B, 0x49, 0xE2, 0x1D, 0x62, 0x17, 0x41,
760 0x63, 0x28, 0x75, 0xDB, 0x7F, 0x6C, 0x92, 0x43,
761 0xD2, 0xD7, 0xC2 };
762 uint8_t *output_data = NULL;
mohammad160387a7eeb2018-11-01 11:25:49 +0200763 size_t output_size = 0;
764 size_t output_length = 0;
765 size_t tag_length = 16;
Jaeden Amero884738a2019-08-16 17:58:31 +0100766 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100767 psa_key_id_t key_id;
Jaeden Amero884738a2019-08-16 17:58:31 +0100768
769 printf("Authenticate encrypt...\t");
770 fflush(stdout);
771
772 /* Initialize PSA Crypto */
773 status = psa_crypto_init();
774 if (status != PSA_SUCCESS) {
775 printf("Failed to initialize PSA Crypto\n");
776 return;
777 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200778
779 output_size = sizeof(input_data) + tag_length;
Jaeden Amero884738a2019-08-16 17:58:31 +0100780 output_data = (uint8_t *)malloc(output_size);
781 if (!output_data) {
782 printf("Out of memory\n");
783 return;
784 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200785
Jaeden Amero884738a2019-08-16 17:58:31 +0100786 /* Import a key */
787 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
788 psa_set_key_algorithm(&attributes, PSA_ALG_CCM);
789 psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
790 psa_set_key_bits(&attributes, 128);
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100791 status = psa_import_key(&attributes, key, sizeof(key), &key_id);
Jaeden Amero884738a2019-08-16 17:58:31 +0100792 psa_reset_key_attributes(&attributes);
mohammad160387a7eeb2018-11-01 11:25:49 +0200793
Jaeden Amero884738a2019-08-16 17:58:31 +0100794 /* Authenticate and encrypt */
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100795 status = psa_aead_encrypt(key_id, PSA_ALG_CCM,
mohammad160387a7eeb2018-11-01 11:25:49 +0200796 nonce, sizeof(nonce),
797 additional_data, sizeof(additional_data),
798 input_data, sizeof(input_data),
799 output_data, output_size,
800 &output_length);
Jaeden Amero884738a2019-08-16 17:58:31 +0100801 if (status != PSA_SUCCESS) {
802 printf("Failed to authenticate and encrypt\n");
803 return;
804 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200805
Jaeden Amero884738a2019-08-16 17:58:31 +0100806 printf("Authenticated and encrypted\n");
807
808 /* Clean up */
809 free(output_data);
810
811 /* Destroy the key */
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100812 psa_destroy_key(key_id);
Jaeden Amero884738a2019-08-16 17:58:31 +0100813
mohammad160387a7eeb2018-11-01 11:25:49 +0200814 mbedtls_psa_crypto_free();
815```
816
Guy Wildc03c0fc2019-09-03 13:18:04 +0300817This example shows how to authenticate and decrypt a message:
mohammad160387a7eeb2018-11-01 11:25:49 +0200818
819```C
mohammad160387a7eeb2018-11-01 11:25:49 +0200820 psa_status_t status;
Ronald Croncf56a0a2020-08-04 09:51:30 +0200821 static const uint8_t key_data[] = {
mohammad160387a7eeb2018-11-01 11:25:49 +0200822 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
Jaeden Amero884738a2019-08-16 17:58:31 +0100823 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF };
824 static const uint8_t nonce[] = {
825 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
826 0x08, 0x09, 0x0A, 0x0B };
827 static const uint8_t additional_data[] = {
828 0xEC, 0x46, 0xBB, 0x63, 0xB0, 0x25,
829 0x20, 0xC3, 0x3C, 0x49, 0xFD, 0x70 };
830 static const uint8_t input_data[] = {
831 0x20, 0x30, 0xE0, 0x36, 0xED, 0x09, 0xA0, 0x45, 0xAF, 0x3C, 0xBA, 0xEE,
832 0x0F, 0xC8, 0x48, 0xAF, 0xCD, 0x89, 0x54, 0xF4, 0xF6, 0x3F, 0x28, 0x9A,
833 0xA1, 0xDD, 0xB2, 0xB8, 0x09, 0xCD, 0x7C, 0xE1, 0x46, 0xE9, 0x98 };
834 uint8_t *output_data = NULL;
mohammad160387a7eeb2018-11-01 11:25:49 +0200835 size_t output_size = 0;
836 size_t output_length = 0;
Jaeden Amero884738a2019-08-16 17:58:31 +0100837 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100838 psa_key_id_t key_id;
Jaeden Amero884738a2019-08-16 17:58:31 +0100839
840 printf("Authenticate decrypt...\t");
841 fflush(stdout);
842
843 /* Initialize PSA Crypto */
844 status = psa_crypto_init();
845 if (status != PSA_SUCCESS) {
846 printf("Failed to initialize PSA Crypto\n");
847 return;
848 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200849
850 output_size = sizeof(input_data);
Jaeden Amero884738a2019-08-16 17:58:31 +0100851 output_data = (uint8_t *)malloc(output_size);
852 if (!output_data) {
853 printf("Out of memory\n");
854 return;
855 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200856
Jaeden Amero884738a2019-08-16 17:58:31 +0100857 /* Import a key */
858 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT);
859 psa_set_key_algorithm(&attributes, PSA_ALG_CCM);
860 psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
861 psa_set_key_bits(&attributes, 128);
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100862 status = psa_import_key(&attributes, key_data, sizeof(key_data), &key_id);
Jaeden Amero884738a2019-08-16 17:58:31 +0100863 if (status != PSA_SUCCESS) {
864 printf("Failed to import a key\n");
865 return;
866 }
867 psa_reset_key_attributes(&attributes);
mohammad160387a7eeb2018-11-01 11:25:49 +0200868
Jaeden Amero884738a2019-08-16 17:58:31 +0100869 /* Authenticate and decrypt */
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100870 status = psa_aead_decrypt(key_id, PSA_ALG_CCM,
mohammad160387a7eeb2018-11-01 11:25:49 +0200871 nonce, sizeof(nonce),
872 additional_data, sizeof(additional_data),
873 input_data, sizeof(input_data),
874 output_data, output_size,
875 &output_length);
Jaeden Amero884738a2019-08-16 17:58:31 +0100876 if (status != PSA_SUCCESS) {
877 printf("Failed to authenticate and decrypt %ld\n", status);
878 return;
879 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200880
Jaeden Amero884738a2019-08-16 17:58:31 +0100881 printf("Authenticated and decrypted\n");
882
883 /* Clean up */
884 free(output_data);
885
886 /* Destroy the key */
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100887 psa_destroy_key(key_id);
Jaeden Amero884738a2019-08-16 17:58:31 +0100888
mohammad160387a7eeb2018-11-01 11:25:49 +0200889 mbedtls_psa_crypto_free();
890```
891
892### Generating and exporting keys
893
Dave Rodgman38699e52023-01-20 12:43:53 +0000894The PSA Crypto API provides a simple way to generate a key or key pair.
mohammad160387a7eeb2018-11-01 11:25:49 +0200895
Guy Wildc03c0fc2019-09-03 13:18:04 +0300896**Prerequisites to using key generation and export APIs:**
897* Initialize the library with a successful call to `psa_crypto_init()`.
mohammad160387a7eeb2018-11-01 11:25:49 +0200898
Guy Wildc03c0fc2019-09-03 13:18:04 +0300899**To generate an ECDSA key:**
Jaeden Amero884738a2019-08-16 17:58:31 +01009001. Set the desired key attributes for key generation by calling
901 `psa_set_key_algorithm()` with the chosen ECDSA algorithm (such as
Dave Rodgman38699e52023-01-20 12:43:53 +0000902 `PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256)`). You only want to export the
903 public key, not the key pair (or private key); therefore, do not
904 set `PSA_KEY_USAGE_EXPORT`.
Jaeden Amero884738a2019-08-16 17:58:31 +01009051. Generate a key by calling `psa_generate_key()`.
Guy Wildc03c0fc2019-09-03 13:18:04 +03009061. Export the generated public key by calling `psa_export_public_key()`:
mohammad160387a7eeb2018-11-01 11:25:49 +0200907```C
Jaeden Amero884738a2019-08-16 17:58:31 +0100908 enum {
909 key_bits = 256,
910 };
911 psa_status_t status;
mohammad160387a7eeb2018-11-01 11:25:49 +0200912 size_t exported_length = 0;
Jaeden Amero884738a2019-08-16 17:58:31 +0100913 static uint8_t exported[PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits)];
914 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100915 psa_key_id_t key_id;
mohammad160387a7eeb2018-11-01 11:25:49 +0200916
Jaeden Amero884738a2019-08-16 17:58:31 +0100917 printf("Generate a key pair...\t");
918 fflush(stdout);
mohammad160387a7eeb2018-11-01 11:25:49 +0200919
Jaeden Amero884738a2019-08-16 17:58:31 +0100920 /* Initialize PSA Crypto */
921 status = psa_crypto_init();
922 if (status != PSA_SUCCESS) {
923 printf("Failed to initialize PSA Crypto\n");
924 return;
925 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200926
927 /* Generate a key */
Gilles Peskine89d8c5c2019-11-26 17:01:59 +0100928 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);
Jaeden Amero884738a2019-08-16 17:58:31 +0100929 psa_set_key_algorithm(&attributes,
930 PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256));
931 psa_set_key_type(&attributes,
Paul Elliott8ff510a2020-06-02 17:19:28 +0100932 PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
Jaeden Amero884738a2019-08-16 17:58:31 +0100933 psa_set_key_bits(&attributes, key_bits);
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100934 status = psa_generate_key(&attributes, &key_id);
Jaeden Amero884738a2019-08-16 17:58:31 +0100935 if (status != PSA_SUCCESS) {
936 printf("Failed to generate key\n");
937 return;
938 }
939 psa_reset_key_attributes(&attributes);
mohammad160387a7eeb2018-11-01 11:25:49 +0200940
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100941 status = psa_export_public_key(key_id, exported, sizeof(exported),
Jaeden Amero884738a2019-08-16 17:58:31 +0100942 &exported_length);
943 if (status != PSA_SUCCESS) {
944 printf("Failed to export public key %ld\n", status);
945 return;
946 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200947
Jaeden Amero884738a2019-08-16 17:58:31 +0100948 printf("Exported a public key\n");
949
950 /* Destroy the key */
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100951 psa_destroy_key(key_id);
Jaeden Amero884738a2019-08-16 17:58:31 +0100952
mohammad160387a7eeb2018-11-01 11:25:49 +0200953 mbedtls_psa_crypto_free();
954```
955
Guy Wild2a9e9f72019-09-04 13:45:54 +0300956### More about the PSA Crypto API
mohammad160387a7eeb2018-11-01 11:25:49 +0200957
Dave Rodgman38699e52023-01-20 12:43:53 +0000958For more information about the PSA Crypto API, please see the
959[PSA Cryptography API Specification](https://arm-software.github.io/psa-api/crypto/).