blob: 507afa163bccd52fc116cf559a68d4077317da9c [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 Rodgman99ff0a72023-01-23 12:31:01 +000023security analyses, hardware and firmware architecture specifications, and an
24open source firmware reference implementation. PSA provides a recipe, based on
Dave Rodgman38699e52023-01-20 12:43:53 +000025industry 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 Rodgman17292f72023-01-23 12:32:51 +000042* [More about the PSA Crypto API](#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 Rodgman17292f72023-01-23 12:32:51 +000075If using PSA Crypto, you must initialize the library by calling
76`psa_crypto_init()` before any other PSA API.
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 Rodgman99ff0a72023-01-23 12:31:01 +0000207* Have a symmetric key. This key's usage flags must include
208 `PSA_KEY_USAGE_ENCRYPT` to allow encryption or `PSA_KEY_USAGE_DECRYPT` to
209 allow decryption.
mohammad160387a7eeb2018-11-01 11:25:49 +0200210
Guy Wildc03c0fc2019-09-03 13:18:04 +0300211**To encrypt a message with a symmetric cipher:**
Dave Rodgman38699e52023-01-20 12:43:53 +00002121. Allocate an operation (`psa_cipher_operation_t`) structure to pass to the
213 cipher functions.
Guy Wild33d421d2019-09-04 09:16:14 +03002141. Initialize the operation structure to zero or to `PSA_CIPHER_OPERATION_INIT`.
Dave Rodgman38699e52023-01-20 12:43:53 +00002151. Call `psa_cipher_encrypt_setup()` to specify the algorithm and the key to be
216 used.
2171. Call either `psa_cipher_generate_iv()` or `psa_cipher_set_iv()` to generate
218 or set the initialization vector (IV). We recommend calling
219 `psa_cipher_generate_iv()`, unless you require a specific IV value.
2201. Call `psa_cipher_update()` with the message to encrypt. You may call this
221 function multiple times, passing successive fragments of the message on
222 successive calls.
2231. Call `psa_cipher_finish()` to end the operation and output the encrypted
224 message.
mohammad160387a7eeb2018-11-01 11:25:49 +0200225
Dave Rodgman38699e52023-01-20 12:43:53 +0000226This example shows how to encrypt data using an AES (Advanced Encryption
227Standard) key in CBC (Cipher Block Chaining) mode with no padding (assuming all
228prerequisites have been fulfilled):
mohammad160387a7eeb2018-11-01 11:25:49 +0200229```c
Jaeden Amerofbdf1502019-11-08 09:59:16 +0000230void encrypt_with_symmetric_ciphers(const uint8_t *key, size_t key_len)
231{
Jaeden Amero884738a2019-08-16 17:58:31 +0100232 enum {
gabor-mezei-armcbcec212020-12-18 14:23:51 +0100233 block_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH(PSA_KEY_TYPE_AES),
Jaeden Amero884738a2019-08-16 17:58:31 +0100234 };
235 psa_status_t status;
236 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
mohammad160387a7eeb2018-11-01 11:25:49 +0200237 psa_algorithm_t alg = PSA_ALG_CBC_NO_PADDING;
Jaeden Amero884738a2019-08-16 17:58:31 +0100238 uint8_t plaintext[block_size] = SOME_PLAINTEXT;
239 uint8_t iv[block_size];
mohammad160387a7eeb2018-11-01 11:25:49 +0200240 size_t iv_len;
Jaeden Amero884738a2019-08-16 17:58:31 +0100241 uint8_t output[block_size];
mohammad160387a7eeb2018-11-01 11:25:49 +0200242 size_t output_len;
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100243 psa_key_id_t key_id;
Jaeden Amero884738a2019-08-16 17:58:31 +0100244 psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
mohammad160387a7eeb2018-11-01 11:25:49 +0200245
Jaeden Amero884738a2019-08-16 17:58:31 +0100246 printf("Encrypt with cipher...\t");
247 fflush(stdout);
mohammad160387a7eeb2018-11-01 11:25:49 +0200248
Jaeden Amero884738a2019-08-16 17:58:31 +0100249 /* Initialize PSA Crypto */
250 status = psa_crypto_init();
251 if (status != PSA_SUCCESS)
252 {
253 printf("Failed to initialize PSA Crypto\n");
254 return;
255 }
256
257 /* Import a key */
258 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
259 psa_set_key_algorithm(&attributes, alg);
260 psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
261 psa_set_key_bits(&attributes, 128);
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100262 status = psa_import_key(&attributes, key, key_len, &key_id);
Jaeden Amero884738a2019-08-16 17:58:31 +0100263 if (status != PSA_SUCCESS) {
264 printf("Failed to import a key\n");
265 return;
266 }
267 psa_reset_key_attributes(&attributes);
268
269 /* Encrypt the plaintext */
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100270 status = psa_cipher_encrypt_setup(&operation, key_id, alg);
Jaeden Amero884738a2019-08-16 17:58:31 +0100271 if (status != PSA_SUCCESS) {
272 printf("Failed to begin cipher operation\n");
273 return;
274 }
275 status = psa_cipher_generate_iv(&operation, iv, sizeof(iv), &iv_len);
276 if (status != PSA_SUCCESS) {
277 printf("Failed to generate IV\n");
278 return;
279 }
280 status = psa_cipher_update(&operation, plaintext, sizeof(plaintext),
281 output, sizeof(output), &output_len);
282 if (status != PSA_SUCCESS) {
283 printf("Failed to update cipher operation\n");
284 return;
285 }
286 status = psa_cipher_finish(&operation, output + output_len,
287 sizeof(output) - output_len, &output_len);
288 if (status != PSA_SUCCESS) {
289 printf("Failed to finish cipher operation\n");
290 return;
291 }
292 printf("Encrypted plaintext\n");
293
mohammad160387a7eeb2018-11-01 11:25:49 +0200294 /* Clean up cipher operation context */
295 psa_cipher_abort(&operation);
Jaeden Amero884738a2019-08-16 17:58:31 +0100296
297 /* Destroy the key */
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100298 psa_destroy_key(key_id);
Jaeden Amero884738a2019-08-16 17:58:31 +0100299
300 mbedtls_psa_crypto_free();
Jaeden Amerofbdf1502019-11-08 09:59:16 +0000301}
mohammad160387a7eeb2018-11-01 11:25:49 +0200302```
303
Guy Wildc03c0fc2019-09-03 13:18:04 +0300304**To decrypt a message with a symmetric cipher:**
Dave Rodgman38699e52023-01-20 12:43:53 +00003051. Allocate an operation (`psa_cipher_operation_t`) structure to pass to the
306 cipher functions.
Guy Wild2a9e9f72019-09-04 13:45:54 +03003071. Initialize the operation structure to zero or to `PSA_CIPHER_OPERATION_INIT`.
Dave Rodgman38699e52023-01-20 12:43:53 +00003081. Call `psa_cipher_decrypt_setup()` to specify the algorithm and the key to be
309 used.
Guy Wildc03c0fc2019-09-03 13:18:04 +03003101. Call `psa_cipher_set_iv()` with the IV for the decryption.
Dave Rodgman38699e52023-01-20 12:43:53 +00003111. Call `psa_cipher_update()` with the message to encrypt. You may call this
312 function multiple times, passing successive fragments of the message on
313 successive calls.
3141. Call `psa_cipher_finish()` to end the operation and output the decrypted
315 message.
mohammad160387a7eeb2018-11-01 11:25:49 +0200316
Dave Rodgman38699e52023-01-20 12:43:53 +0000317This example shows how to decrypt encrypted data using an AES key in CBC mode
318with no padding (assuming all prerequisites have been fulfilled):
mohammad160387a7eeb2018-11-01 11:25:49 +0200319```c
Jaeden Amerofbdf1502019-11-08 09:59:16 +0000320void decrypt_with_symmetric_ciphers(const uint8_t *key, size_t key_len)
321{
Jaeden Amero884738a2019-08-16 17:58:31 +0100322 enum {
gabor-mezei-armcbcec212020-12-18 14:23:51 +0100323 block_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH(PSA_KEY_TYPE_AES),
Jaeden Amero884738a2019-08-16 17:58:31 +0100324 };
325 psa_status_t status;
326 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
mohammad160387a7eeb2018-11-01 11:25:49 +0200327 psa_algorithm_t alg = PSA_ALG_CBC_NO_PADDING;
Jaeden Amero884738a2019-08-16 17:58:31 +0100328 psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
329 uint8_t ciphertext[block_size] = SOME_CIPHERTEXT;
330 uint8_t iv[block_size] = ENCRYPTED_WITH_IV;
Jaeden Amero884738a2019-08-16 17:58:31 +0100331 uint8_t output[block_size];
mohammad160387a7eeb2018-11-01 11:25:49 +0200332 size_t output_len;
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100333 psa_key_id_t key_id;
mohammad160387a7eeb2018-11-01 11:25:49 +0200334
Jaeden Amero884738a2019-08-16 17:58:31 +0100335 printf("Decrypt with cipher...\t");
336 fflush(stdout);
mohammad160387a7eeb2018-11-01 11:25:49 +0200337
Jaeden Amero884738a2019-08-16 17:58:31 +0100338 /* Initialize PSA Crypto */
339 status = psa_crypto_init();
340 if (status != PSA_SUCCESS)
341 {
342 printf("Failed to initialize PSA Crypto\n");
343 return;
344 }
345
346 /* Import a key */
347 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT);
348 psa_set_key_algorithm(&attributes, alg);
349 psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
350 psa_set_key_bits(&attributes, 128);
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100351 status = psa_import_key(&attributes, key, key_len, &key_id);
Jaeden Amero884738a2019-08-16 17:58:31 +0100352 if (status != PSA_SUCCESS) {
353 printf("Failed to import a key\n");
354 return;
355 }
356 psa_reset_key_attributes(&attributes);
357
358 /* Decrypt the ciphertext */
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100359 status = psa_cipher_decrypt_setup(&operation, key_id, alg);
Jaeden Amero884738a2019-08-16 17:58:31 +0100360 if (status != PSA_SUCCESS) {
361 printf("Failed to begin cipher operation\n");
362 return;
363 }
364 status = psa_cipher_set_iv(&operation, iv, sizeof(iv));
365 if (status != PSA_SUCCESS) {
366 printf("Failed to set IV\n");
367 return;
368 }
369 status = psa_cipher_update(&operation, ciphertext, sizeof(ciphertext),
370 output, sizeof(output), &output_len);
371 if (status != PSA_SUCCESS) {
372 printf("Failed to update cipher operation\n");
373 return;
374 }
375 status = psa_cipher_finish(&operation, output + output_len,
376 sizeof(output) - output_len, &output_len);
377 if (status != PSA_SUCCESS) {
378 printf("Failed to finish cipher operation\n");
379 return;
380 }
381 printf("Decrypted ciphertext\n");
382
mohammad160387a7eeb2018-11-01 11:25:49 +0200383 /* Clean up cipher operation context */
384 psa_cipher_abort(&operation);
Jaeden Amero884738a2019-08-16 17:58:31 +0100385
386 /* Destroy the key */
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100387 psa_destroy_key(key_id);
Jaeden Amero884738a2019-08-16 17:58:31 +0100388
389 mbedtls_psa_crypto_free();
Jaeden Amerofbdf1502019-11-08 09:59:16 +0000390}
mohammad160387a7eeb2018-11-01 11:25:49 +0200391```
392
393#### Handling cipher operation contexts
394
Dave Rodgman38699e52023-01-20 12:43:53 +0000395After you've initialized the operation structure with a successful call to
396`psa_cipher_encrypt_setup()` or `psa_cipher_decrypt_setup()`, you can terminate
397the operation at any time by calling `psa_cipher_abort()`.
mohammad160387a7eeb2018-11-01 11:25:49 +0200398
Dave Rodgman38699e52023-01-20 12:43:53 +0000399The call to `psa_cipher_abort()` frees any resources associated with the
400operation, except for the operation structure itself.
mohammad160387a7eeb2018-11-01 11:25:49 +0200401
Dave Rodgman38699e52023-01-20 12:43:53 +0000402The PSA Crypto API implicitly calls `psa_cipher_abort()` when:
403* A call to `psa_cipher_generate_iv()`, `psa_cipher_set_iv()` or
404 `psa_cipher_update()` fails (returning any status other than `PSA_SUCCESS`).
Guy Wildc03c0fc2019-09-03 13:18:04 +0300405* A call to `psa_cipher_finish()` succeeds or fails.
mohammad160387a7eeb2018-11-01 11:25:49 +0200406
Dave Rodgman38699e52023-01-20 12:43:53 +0000407After an implicit or explicit call to `psa_cipher_abort()`, the operation
408structure is invalidated; in other words, you cannot reuse the operation
409structure for the same operation. You can, however, reuse the operation
410structure for a different operation by calling either
411`psa_cipher_encrypt_setup()` or `psa_cipher_decrypt_setup()` again.
mohammad160387a7eeb2018-11-01 11:25:49 +0200412
Dave Rodgman38699e52023-01-20 12:43:53 +0000413You must call `psa_cipher_abort()` at some point for any operation that is
414initialized successfully (by a successful call to `psa_cipher_encrypt_setup()`
415or `psa_cipher_decrypt_setup()`).
Guy Wildc03c0fc2019-09-03 13:18:04 +0300416
Dave Rodgman38699e52023-01-20 12:43:53 +0000417Making multiple sequential calls to `psa_cipher_abort()` on an operation that
418is terminated (either implicitly or explicitly) is safe and has no effect.
mohammad160387a7eeb2018-11-01 11:25:49 +0200419
420### Hashing a message
421
Dave Rodgman38699e52023-01-20 12:43:53 +0000422The PSA Crypto API lets you compute and verify hashes using various hashing
Jaeden Amero884738a2019-08-16 17:58:31 +0100423algorithms.
mohammad160387a7eeb2018-11-01 11:25:49 +0200424
Guy Wildc03c0fc2019-09-03 13:18:04 +0300425**Prerequisites to working with the hash APIs:**
426* Initialize the library with a successful call to `psa_crypto_init()`.
mohammad160387a7eeb2018-11-01 11:25:49 +0200427
Guy Wildc03c0fc2019-09-03 13:18:04 +0300428**To calculate a hash:**
Dave Rodgman38699e52023-01-20 12:43:53 +00004291. Allocate an operation structure (`psa_hash_operation_t`) to pass to the hash
430 functions.
Guy Wildeefc5172019-09-04 09:16:53 +03004311. Initialize the operation structure to zero or to `PSA_HASH_OPERATION_INIT`.
4321. Call `psa_hash_setup()` to specify the hash algorithm.
Dave Rodgman38699e52023-01-20 12:43:53 +00004331. Call `psa_hash_update()` with the message to encrypt. You may call this
434 function multiple times, passing successive fragments of the message on
435 successive calls.
4361. Call `psa_hash_finish()` to calculate the hash, or `psa_hash_verify()` to
437 compare the computed hash with an expected hash value.
mohammad160387a7eeb2018-11-01 11:25:49 +0200438
Guy Wild2a9e9f72019-09-04 13:45:54 +0300439This example shows how to calculate the SHA-256 hash of a message:
mohammad160387a7eeb2018-11-01 11:25:49 +0200440```c
Jaeden Amero884738a2019-08-16 17:58:31 +0100441 psa_status_t status;
mohammad160387a7eeb2018-11-01 11:25:49 +0200442 psa_algorithm_t alg = PSA_ALG_SHA_256;
Jaeden Amero884738a2019-08-16 17:58:31 +0100443 psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
mohammad160387a7eeb2018-11-01 11:25:49 +0200444 unsigned char input[] = { 'a', 'b', 'c' };
445 unsigned char actual_hash[PSA_HASH_MAX_SIZE];
446 size_t actual_hash_len;
447
Jaeden Amero884738a2019-08-16 17:58:31 +0100448 printf("Hash a message...\t");
449 fflush(stdout);
450
451 /* Initialize PSA Crypto */
452 status = psa_crypto_init();
453 if (status != PSA_SUCCESS) {
454 printf("Failed to initialize PSA Crypto\n");
455 return;
456 }
457
mohammad160387a7eeb2018-11-01 11:25:49 +0200458 /* Compute hash of message */
Jaeden Amero884738a2019-08-16 17:58:31 +0100459 status = psa_hash_setup(&operation, alg);
460 if (status != PSA_SUCCESS) {
461 printf("Failed to begin hash operation\n");
462 return;
463 }
464 status = psa_hash_update(&operation, input, sizeof(input));
465 if (status != PSA_SUCCESS) {
466 printf("Failed to update hash operation\n");
467 return;
468 }
469 status = psa_hash_finish(&operation, actual_hash, sizeof(actual_hash),
470 &actual_hash_len);
471 if (status != PSA_SUCCESS) {
472 printf("Failed to finish hash operation\n");
473 return;
474 }
475
476 printf("Hashed a message\n");
mohammad160387a7eeb2018-11-01 11:25:49 +0200477
478 /* Clean up hash operation context */
479 psa_hash_abort(&operation);
Jaeden Amero884738a2019-08-16 17:58:31 +0100480
481 mbedtls_psa_crypto_free();
mohammad160387a7eeb2018-11-01 11:25:49 +0200482```
483
Guy Wild2a9e9f72019-09-04 13:45:54 +0300484This example shows how to verify the SHA-256 hash of a message:
mohammad160387a7eeb2018-11-01 11:25:49 +0200485```c
Jaeden Amero884738a2019-08-16 17:58:31 +0100486 psa_status_t status;
mohammad160387a7eeb2018-11-01 11:25:49 +0200487 psa_algorithm_t alg = PSA_ALG_SHA_256;
Jaeden Amero884738a2019-08-16 17:58:31 +0100488 psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
mohammad160387a7eeb2018-11-01 11:25:49 +0200489 unsigned char input[] = { 'a', 'b', 'c' };
490 unsigned char expected_hash[] = {
491 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, 0xde,
492 0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
493 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad
494 };
gabor-mezei-armcbcec212020-12-18 14:23:51 +0100495 size_t expected_hash_len = PSA_HASH_LENGTH(alg);
mohammad160387a7eeb2018-11-01 11:25:49 +0200496
Jaeden Amero884738a2019-08-16 17:58:31 +0100497 printf("Verify a hash...\t");
498 fflush(stdout);
499
500 /* Initialize PSA Crypto */
501 status = psa_crypto_init();
502 if (status != PSA_SUCCESS) {
503 printf("Failed to initialize PSA Crypto\n");
504 return;
505 }
506
mohammad160387a7eeb2018-11-01 11:25:49 +0200507 /* Verify message hash */
Jaeden Amero884738a2019-08-16 17:58:31 +0100508 status = psa_hash_setup(&operation, alg);
509 if (status != PSA_SUCCESS) {
510 printf("Failed to begin hash operation\n");
511 return;
512 }
513 status = psa_hash_update(&operation, input, sizeof(input));
514 if (status != PSA_SUCCESS) {
515 printf("Failed to update hash operation\n");
516 return;
517 }
518 status = psa_hash_verify(&operation, expected_hash, expected_hash_len);
519 if (status != PSA_SUCCESS) {
520 printf("Failed to verify hash\n");
521 return;
522 }
523
524 printf("Verified a hash\n");
525
526 /* Clean up hash operation context */
527 psa_hash_abort(&operation);
528
529 mbedtls_psa_crypto_free();
mohammad160387a7eeb2018-11-01 11:25:49 +0200530```
531
Dave Rodgman38699e52023-01-20 12:43:53 +0000532The API provides the macro `PSA_HASH_LENGTH`, which returns the expected hash
533length (in bytes) for the specified algorithm.
mohammad160387a7eeb2018-11-01 11:25:49 +0200534
535#### Handling hash operation contexts
536
Dave Rodgman38699e52023-01-20 12:43:53 +0000537After a successful call to `psa_hash_setup()`, you can terminate the operation
538at any time by calling `psa_hash_abort()`. The call to `psa_hash_abort()` frees
539any resources associated with the operation, except for the operation structure
540itself.
mohammad160387a7eeb2018-11-01 11:25:49 +0200541
Dave Rodgman38699e52023-01-20 12:43:53 +0000542The PSA Crypto API implicitly calls `psa_hash_abort()` when:
5431. A call to `psa_hash_update()` fails (returning any status other than
544 `PSA_SUCCESS`).
Guy Wildc03c0fc2019-09-03 13:18:04 +03005451. A call to `psa_hash_finish()` succeeds or fails.
5461. A call to `psa_hash_verify()` succeeds or fails.
mohammad160387a7eeb2018-11-01 11:25:49 +0200547
Dave Rodgman38699e52023-01-20 12:43:53 +0000548After an implicit or explicit call to `psa_hash_abort()`, the operation
549structure is invalidated; in other words, you cannot reuse the operation
550structure for the same operation. You can, however, reuse the operation
551structure for a different operation by calling `psa_hash_setup()` again.
mohammad160387a7eeb2018-11-01 11:25:49 +0200552
Dave Rodgman38699e52023-01-20 12:43:53 +0000553You must call `psa_hash_abort()` at some point for any operation that is
554initialized successfully (by a successful call to `psa_hash_setup()`) .
mohammad160387a7eeb2018-11-01 11:25:49 +0200555
Dave Rodgman38699e52023-01-20 12:43:53 +0000556Making multiple sequential calls to `psa_hash_abort()` on an operation that has
557already been terminated (either implicitly or explicitly) is safe and has no
558effect.
mohammad160387a7eeb2018-11-01 11:25:49 +0200559
560### Generating a random value
561
Dave Rodgman38699e52023-01-20 12:43:53 +0000562The PSA Crypto API can generate random data.
mohammad160387a7eeb2018-11-01 11:25:49 +0200563
Guy Wild802b19f2019-09-03 16:40:44 +0300564**Prerequisites to generating random data:**
Jaeden Amero884738a2019-08-16 17:58:31 +0100565* Initialize the library with a successful call to `psa_crypto_init()`.
mohammad160387a7eeb2018-11-01 11:25:49 +0200566
Dave Rodgman38699e52023-01-20 12:43:53 +0000567<span class="notes">**Note:** To generate a random key, use `psa_generate_key()`
568instead of `psa_generate_random()`.</span>
Guy Wild802b19f2019-09-03 16:40:44 +0300569
Dave Rodgman38699e52023-01-20 12:43:53 +0000570This example shows how to generate ten bytes of random data by calling
571`psa_generate_random()`:
mohammad160387a7eeb2018-11-01 11:25:49 +0200572```C
573 psa_status_t status;
574 uint8_t random[10] = { 0 };
mohammad160387a7eeb2018-11-01 11:25:49 +0200575
Jaeden Amero884738a2019-08-16 17:58:31 +0100576 printf("Generate random...\t");
577 fflush(stdout);
578
579 /* Initialize PSA Crypto */
580 status = psa_crypto_init();
581 if (status != PSA_SUCCESS) {
582 printf("Failed to initialize PSA Crypto\n");
583 return;
584 }
585
586 status = psa_generate_random(random, sizeof(random));
587 if (status != PSA_SUCCESS) {
588 printf("Failed to generate a random value\n");
589 return;
590 }
591
592 printf("Generated random data\n");
593
594 /* Clean up */
mohammad160387a7eeb2018-11-01 11:25:49 +0200595 mbedtls_psa_crypto_free();
596```
597
598### Deriving a new key from an existing key
599
Dave Rodgman38699e52023-01-20 12:43:53 +0000600The PSA Crypto API provides a key derivation API that lets you derive new keys
601from existing ones. The key derivation API has functions to take inputs,
602including other keys and data, and functions to generate outputs, such as
603new keys or other data.
mohammad160387a7eeb2018-11-01 11:25:49 +0200604
Guy Wildc03c0fc2019-09-03 13:18:04 +0300605You must first initialize and set up a key derivation context,
Dave Rodgman99ff0a72023-01-23 12:31:01 +0000606provided with a key and, optionally, other data. Then, use the key derivation
607context to either read derived data to a buffer or send derived data directly
608to a key slot.
Guy Wildc03c0fc2019-09-03 13:18:04 +0300609
Dave Rodgman99ff0a72023-01-23 12:31:01 +0000610See the documentation for the particular algorithm (such as HKDF or the
611TLS 1.2 PRF) for information about which inputs to pass when, and when you can
612obtain which outputs.
Guy Wildc03c0fc2019-09-03 13:18:04 +0300613
614**Prerequisites to working with the key derivation APIs:**
615* Initialize the library with a successful call to `psa_crypto_init()`.
Jaeden Amero884738a2019-08-16 17:58:31 +0100616* Use a key with the appropriate attributes set:
617 * Usage flags set for key derivation (`PSA_KEY_USAGE_DERIVE`)
618 * Key type set to `PSA_KEY_TYPE_DERIVE`.
619 * Algorithm set to a key derivation algorithm
Guy Wild2a9e9f72019-09-04 13:45:54 +0300620 (for example, `PSA_ALG_HKDF(PSA_ALG_SHA_256)`).
mohammad160387a7eeb2018-11-01 11:25:49 +0200621
Guy Wildc03c0fc2019-09-03 13:18:04 +0300622**To derive a new AES-CTR 128-bit encryption key into a given key slot using HKDF
Guy Wild2a9e9f72019-09-04 13:45:54 +0300623with a given key, salt and info:**
Guy Wildc03c0fc2019-09-03 13:18:04 +0300624
6251. Set up the key derivation context using the `psa_key_derivation_setup()`
Jaeden Amero884738a2019-08-16 17:58:31 +0100626function, specifying the derivation algorithm `PSA_ALG_HKDF(PSA_ALG_SHA_256)`.
Guy Wild29008112019-09-05 11:38:14 +03006271. Provide an optional salt with `psa_key_derivation_input_bytes()`.
6281. Provide info with `psa_key_derivation_input_bytes()`.
Dave Rodgman99ff0a72023-01-23 12:31:01 +00006291. Provide a secret with `psa_key_derivation_input_key()`, referencing a key
630 that can be used for key derivation.
Jaeden Amero884738a2019-08-16 17:58:31 +01006311. Set the key attributes desired for the new derived key. We'll set
Dave Rodgman99ff0a72023-01-23 12:31:01 +0000632 the `PSA_KEY_USAGE_ENCRYPT` usage flag and the `PSA_ALG_CTR` algorithm for
633 this example.
Jaeden Amero884738a2019-08-16 17:58:31 +01006341. Derive the key by calling `psa_key_derivation_output_key()`.
6351. Clean up the key derivation context.
mohammad160387a7eeb2018-11-01 11:25:49 +0200636
Guy Wildc03c0fc2019-09-03 13:18:04 +0300637At this point, the derived key slot holds a new 128-bit AES-CTR encryption key
Guy Wildce560772019-09-05 11:35:16 +0300638derived from the key, salt and info provided:
mohammad160387a7eeb2018-11-01 11:25:49 +0200639```C
Jaeden Amero884738a2019-08-16 17:58:31 +0100640 psa_status_t status;
641 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
642 static const unsigned char key[] = {
mohammad160387a7eeb2018-11-01 11:25:49 +0200643 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
644 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
645 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
646 0x0b };
Jaeden Amero884738a2019-08-16 17:58:31 +0100647 static const unsigned char salt[] = {
648 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
649 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c };
650 static const unsigned char info[] = {
651 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6,
652 0xf7, 0xf8, 0xf9 };
mohammad160387a7eeb2018-11-01 11:25:49 +0200653 psa_algorithm_t alg = PSA_ALG_HKDF(PSA_ALG_SHA_256);
Jaeden Amero884738a2019-08-16 17:58:31 +0100654 psa_key_derivation_operation_t operation =
655 PSA_KEY_DERIVATION_OPERATION_INIT;
mohammad160387a7eeb2018-11-01 11:25:49 +0200656 size_t derived_bits = 128;
657 size_t capacity = PSA_BITS_TO_BYTES(derived_bits);
Ronald Croncf56a0a2020-08-04 09:51:30 +0200658 psa_key_id_t base_key;
659 psa_key_id_t derived_key;
mohammad160387a7eeb2018-11-01 11:25:49 +0200660
Jaeden Amero884738a2019-08-16 17:58:31 +0100661 printf("Derive a key (HKDF)...\t");
662 fflush(stdout);
663
664 /* Initialize PSA Crypto */
mohammad160387a7eeb2018-11-01 11:25:49 +0200665 status = psa_crypto_init();
Jaeden Amero884738a2019-08-16 17:58:31 +0100666 if (status != PSA_SUCCESS) {
667 printf("Failed to initialize PSA Crypto\n");
668 return;
669 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200670
Jaeden Amero884738a2019-08-16 17:58:31 +0100671 /* Import a key for use in key derivation. If such a key has already been
672 * generated or imported, you can skip this part. */
673 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE);
674 psa_set_key_algorithm(&attributes, alg);
675 psa_set_key_type(&attributes, PSA_KEY_TYPE_DERIVE);
676 status = psa_import_key(&attributes, key, sizeof(key), &base_key);
677 if (status != PSA_SUCCESS) {
678 printf("Failed to import a key\n");
679 return;
680 }
681 psa_reset_key_attributes(&attributes);
mohammad160387a7eeb2018-11-01 11:25:49 +0200682
Jaeden Amero884738a2019-08-16 17:58:31 +0100683 /* Derive a key */
684 status = psa_key_derivation_setup(&operation, alg);
685 if (status != PSA_SUCCESS) {
686 printf("Failed to begin key derivation\n");
687 return;
688 }
689 status = psa_key_derivation_set_capacity(&operation, capacity);
690 if (status != PSA_SUCCESS) {
691 printf("Failed to set capacity\n");
692 return;
693 }
694 status = psa_key_derivation_input_bytes(&operation,
695 PSA_KEY_DERIVATION_INPUT_SALT,
696 salt, sizeof(salt));
697 if (status != PSA_SUCCESS) {
698 printf("Failed to input salt (extract)\n");
699 return;
700 }
701 status = psa_key_derivation_input_key(&operation,
702 PSA_KEY_DERIVATION_INPUT_SECRET,
703 base_key);
704 if (status != PSA_SUCCESS) {
705 printf("Failed to input key (extract)\n");
706 return;
707 }
708 status = psa_key_derivation_input_bytes(&operation,
709 PSA_KEY_DERIVATION_INPUT_INFO,
710 info, sizeof(info));
711 if (status != PSA_SUCCESS) {
712 printf("Failed to input info (expand)\n");
713 return;
714 }
715 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
716 psa_set_key_algorithm(&attributes, PSA_ALG_CTR);
717 psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
718 psa_set_key_bits(&attributes, 128);
719 status = psa_key_derivation_output_key(&attributes, &operation,
720 &derived_key);
721 if (status != PSA_SUCCESS) {
722 printf("Failed to derive key\n");
723 return;
724 }
725 psa_reset_key_attributes(&attributes);
mohammad160387a7eeb2018-11-01 11:25:49 +0200726
Jaeden Amero884738a2019-08-16 17:58:31 +0100727 printf("Derived key\n");
mohammad160387a7eeb2018-11-01 11:25:49 +0200728
Jaeden Amero884738a2019-08-16 17:58:31 +0100729 /* Clean up key derivation operation */
730 psa_key_derivation_abort(&operation);
mohammad160387a7eeb2018-11-01 11:25:49 +0200731
Jaeden Amero884738a2019-08-16 17:58:31 +0100732 /* Destroy the keys */
733 psa_destroy_key(derived_key);
734 psa_destroy_key(base_key);
mohammad160387a7eeb2018-11-01 11:25:49 +0200735
mohammad160387a7eeb2018-11-01 11:25:49 +0200736 mbedtls_psa_crypto_free();
737```
738
739### Authenticating and encrypting or decrypting a message
740
Dave Rodgman38699e52023-01-20 12:43:53 +0000741The PSA Crypto API provides a simple way to authenticate and encrypt with
742associated data (AEAD), supporting the `PSA_ALG_CCM` algorithm.
mohammad160387a7eeb2018-11-01 11:25:49 +0200743
Guy Wildc03c0fc2019-09-03 13:18:04 +0300744**Prerequisites to working with the AEAD cipher APIs:**
745* Initialize the library with a successful call to `psa_crypto_init()`.
Dave Rodgman38699e52023-01-20 12:43:53 +0000746* The key attributes for the key used for derivation must have the
747 `PSA_KEY_USAGE_ENCRYPT` or `PSA_KEY_USAGE_DECRYPT` usage flags.
mohammad160387a7eeb2018-11-01 11:25:49 +0200748
Guy Wildc03c0fc2019-09-03 13:18:04 +0300749This example shows how to authenticate and encrypt a message:
mohammad160387a7eeb2018-11-01 11:25:49 +0200750```C
mohammad160387a7eeb2018-11-01 11:25:49 +0200751 psa_status_t status;
Jaeden Amero884738a2019-08-16 17:58:31 +0100752 static const uint8_t key[] = {
753 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
754 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF };
755 static const uint8_t nonce[] = {
756 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
757 0x08, 0x09, 0x0A, 0x0B };
758 static const uint8_t additional_data[] = {
759 0xEC, 0x46, 0xBB, 0x63, 0xB0, 0x25,
760 0x20, 0xC3, 0x3C, 0x49, 0xFD, 0x70 };
761 static const uint8_t input_data[] = {
762 0xB9, 0x6B, 0x49, 0xE2, 0x1D, 0x62, 0x17, 0x41,
763 0x63, 0x28, 0x75, 0xDB, 0x7F, 0x6C, 0x92, 0x43,
764 0xD2, 0xD7, 0xC2 };
765 uint8_t *output_data = NULL;
mohammad160387a7eeb2018-11-01 11:25:49 +0200766 size_t output_size = 0;
767 size_t output_length = 0;
768 size_t tag_length = 16;
Jaeden Amero884738a2019-08-16 17:58:31 +0100769 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100770 psa_key_id_t key_id;
Jaeden Amero884738a2019-08-16 17:58:31 +0100771
772 printf("Authenticate encrypt...\t");
773 fflush(stdout);
774
775 /* Initialize PSA Crypto */
776 status = psa_crypto_init();
777 if (status != PSA_SUCCESS) {
778 printf("Failed to initialize PSA Crypto\n");
779 return;
780 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200781
782 output_size = sizeof(input_data) + tag_length;
Jaeden Amero884738a2019-08-16 17:58:31 +0100783 output_data = (uint8_t *)malloc(output_size);
784 if (!output_data) {
785 printf("Out of memory\n");
786 return;
787 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200788
Jaeden Amero884738a2019-08-16 17:58:31 +0100789 /* Import a key */
790 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
791 psa_set_key_algorithm(&attributes, PSA_ALG_CCM);
792 psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
793 psa_set_key_bits(&attributes, 128);
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100794 status = psa_import_key(&attributes, key, sizeof(key), &key_id);
Jaeden Amero884738a2019-08-16 17:58:31 +0100795 psa_reset_key_attributes(&attributes);
mohammad160387a7eeb2018-11-01 11:25:49 +0200796
Jaeden Amero884738a2019-08-16 17:58:31 +0100797 /* Authenticate and encrypt */
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100798 status = psa_aead_encrypt(key_id, PSA_ALG_CCM,
mohammad160387a7eeb2018-11-01 11:25:49 +0200799 nonce, sizeof(nonce),
800 additional_data, sizeof(additional_data),
801 input_data, sizeof(input_data),
802 output_data, output_size,
803 &output_length);
Jaeden Amero884738a2019-08-16 17:58:31 +0100804 if (status != PSA_SUCCESS) {
805 printf("Failed to authenticate and encrypt\n");
806 return;
807 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200808
Jaeden Amero884738a2019-08-16 17:58:31 +0100809 printf("Authenticated and encrypted\n");
810
811 /* Clean up */
812 free(output_data);
813
814 /* Destroy the key */
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100815 psa_destroy_key(key_id);
Jaeden Amero884738a2019-08-16 17:58:31 +0100816
mohammad160387a7eeb2018-11-01 11:25:49 +0200817 mbedtls_psa_crypto_free();
818```
819
Guy Wildc03c0fc2019-09-03 13:18:04 +0300820This example shows how to authenticate and decrypt a message:
mohammad160387a7eeb2018-11-01 11:25:49 +0200821
822```C
mohammad160387a7eeb2018-11-01 11:25:49 +0200823 psa_status_t status;
Ronald Croncf56a0a2020-08-04 09:51:30 +0200824 static const uint8_t key_data[] = {
mohammad160387a7eeb2018-11-01 11:25:49 +0200825 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
Jaeden Amero884738a2019-08-16 17:58:31 +0100826 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF };
827 static const uint8_t nonce[] = {
828 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
829 0x08, 0x09, 0x0A, 0x0B };
830 static const uint8_t additional_data[] = {
831 0xEC, 0x46, 0xBB, 0x63, 0xB0, 0x25,
832 0x20, 0xC3, 0x3C, 0x49, 0xFD, 0x70 };
833 static const uint8_t input_data[] = {
834 0x20, 0x30, 0xE0, 0x36, 0xED, 0x09, 0xA0, 0x45, 0xAF, 0x3C, 0xBA, 0xEE,
835 0x0F, 0xC8, 0x48, 0xAF, 0xCD, 0x89, 0x54, 0xF4, 0xF6, 0x3F, 0x28, 0x9A,
836 0xA1, 0xDD, 0xB2, 0xB8, 0x09, 0xCD, 0x7C, 0xE1, 0x46, 0xE9, 0x98 };
837 uint8_t *output_data = NULL;
mohammad160387a7eeb2018-11-01 11:25:49 +0200838 size_t output_size = 0;
839 size_t output_length = 0;
Jaeden Amero884738a2019-08-16 17:58:31 +0100840 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100841 psa_key_id_t key_id;
Jaeden Amero884738a2019-08-16 17:58:31 +0100842
843 printf("Authenticate decrypt...\t");
844 fflush(stdout);
845
846 /* Initialize PSA Crypto */
847 status = psa_crypto_init();
848 if (status != PSA_SUCCESS) {
849 printf("Failed to initialize PSA Crypto\n");
850 return;
851 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200852
853 output_size = sizeof(input_data);
Jaeden Amero884738a2019-08-16 17:58:31 +0100854 output_data = (uint8_t *)malloc(output_size);
855 if (!output_data) {
856 printf("Out of memory\n");
857 return;
858 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200859
Jaeden Amero884738a2019-08-16 17:58:31 +0100860 /* Import a key */
861 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT);
862 psa_set_key_algorithm(&attributes, PSA_ALG_CCM);
863 psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
864 psa_set_key_bits(&attributes, 128);
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100865 status = psa_import_key(&attributes, key_data, sizeof(key_data), &key_id);
Jaeden Amero884738a2019-08-16 17:58:31 +0100866 if (status != PSA_SUCCESS) {
867 printf("Failed to import a key\n");
868 return;
869 }
870 psa_reset_key_attributes(&attributes);
mohammad160387a7eeb2018-11-01 11:25:49 +0200871
Jaeden Amero884738a2019-08-16 17:58:31 +0100872 /* Authenticate and decrypt */
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100873 status = psa_aead_decrypt(key_id, PSA_ALG_CCM,
mohammad160387a7eeb2018-11-01 11:25:49 +0200874 nonce, sizeof(nonce),
875 additional_data, sizeof(additional_data),
876 input_data, sizeof(input_data),
877 output_data, output_size,
878 &output_length);
Jaeden Amero884738a2019-08-16 17:58:31 +0100879 if (status != PSA_SUCCESS) {
880 printf("Failed to authenticate and decrypt %ld\n", status);
881 return;
882 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200883
Jaeden Amero884738a2019-08-16 17:58:31 +0100884 printf("Authenticated and decrypted\n");
885
886 /* Clean up */
887 free(output_data);
888
889 /* Destroy the key */
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100890 psa_destroy_key(key_id);
Jaeden Amero884738a2019-08-16 17:58:31 +0100891
mohammad160387a7eeb2018-11-01 11:25:49 +0200892 mbedtls_psa_crypto_free();
893```
894
895### Generating and exporting keys
896
Dave Rodgman38699e52023-01-20 12:43:53 +0000897The PSA Crypto API provides a simple way to generate a key or key pair.
mohammad160387a7eeb2018-11-01 11:25:49 +0200898
Guy Wildc03c0fc2019-09-03 13:18:04 +0300899**Prerequisites to using key generation and export APIs:**
900* Initialize the library with a successful call to `psa_crypto_init()`.
mohammad160387a7eeb2018-11-01 11:25:49 +0200901
Guy Wildc03c0fc2019-09-03 13:18:04 +0300902**To generate an ECDSA key:**
Jaeden Amero884738a2019-08-16 17:58:31 +01009031. Set the desired key attributes for key generation by calling
904 `psa_set_key_algorithm()` with the chosen ECDSA algorithm (such as
Dave Rodgman38699e52023-01-20 12:43:53 +0000905 `PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256)`). You only want to export the
906 public key, not the key pair (or private key); therefore, do not
907 set `PSA_KEY_USAGE_EXPORT`.
Jaeden Amero884738a2019-08-16 17:58:31 +01009081. Generate a key by calling `psa_generate_key()`.
Guy Wildc03c0fc2019-09-03 13:18:04 +03009091. Export the generated public key by calling `psa_export_public_key()`:
mohammad160387a7eeb2018-11-01 11:25:49 +0200910```C
Jaeden Amero884738a2019-08-16 17:58:31 +0100911 enum {
912 key_bits = 256,
913 };
914 psa_status_t status;
mohammad160387a7eeb2018-11-01 11:25:49 +0200915 size_t exported_length = 0;
Jaeden Amero884738a2019-08-16 17:58:31 +0100916 static uint8_t exported[PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits)];
917 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100918 psa_key_id_t key_id;
mohammad160387a7eeb2018-11-01 11:25:49 +0200919
Jaeden Amero884738a2019-08-16 17:58:31 +0100920 printf("Generate a key pair...\t");
921 fflush(stdout);
mohammad160387a7eeb2018-11-01 11:25:49 +0200922
Jaeden Amero884738a2019-08-16 17:58:31 +0100923 /* Initialize PSA Crypto */
924 status = psa_crypto_init();
925 if (status != PSA_SUCCESS) {
926 printf("Failed to initialize PSA Crypto\n");
927 return;
928 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200929
930 /* Generate a key */
Gilles Peskine89d8c5c2019-11-26 17:01:59 +0100931 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);
Jaeden Amero884738a2019-08-16 17:58:31 +0100932 psa_set_key_algorithm(&attributes,
933 PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256));
934 psa_set_key_type(&attributes,
Paul Elliott8ff510a2020-06-02 17:19:28 +0100935 PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
Jaeden Amero884738a2019-08-16 17:58:31 +0100936 psa_set_key_bits(&attributes, key_bits);
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100937 status = psa_generate_key(&attributes, &key_id);
Jaeden Amero884738a2019-08-16 17:58:31 +0100938 if (status != PSA_SUCCESS) {
939 printf("Failed to generate key\n");
940 return;
941 }
942 psa_reset_key_attributes(&attributes);
mohammad160387a7eeb2018-11-01 11:25:49 +0200943
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100944 status = psa_export_public_key(key_id, exported, sizeof(exported),
Jaeden Amero884738a2019-08-16 17:58:31 +0100945 &exported_length);
946 if (status != PSA_SUCCESS) {
947 printf("Failed to export public key %ld\n", status);
948 return;
949 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200950
Jaeden Amero884738a2019-08-16 17:58:31 +0100951 printf("Exported a public key\n");
952
953 /* Destroy the key */
Andrzej Kureke3ed8242021-11-19 13:40:20 +0100954 psa_destroy_key(key_id);
Jaeden Amero884738a2019-08-16 17:58:31 +0100955
mohammad160387a7eeb2018-11-01 11:25:49 +0200956 mbedtls_psa_crypto_free();
957```
958
Guy Wild2a9e9f72019-09-04 13:45:54 +0300959### More about the PSA Crypto API
mohammad160387a7eeb2018-11-01 11:25:49 +0200960
Dave Rodgman38699e52023-01-20 12:43:53 +0000961For more information about the PSA Crypto API, please see the
962[PSA Cryptography API Specification](https://arm-software.github.io/psa-api/crypto/).