blob: 3097a1ae9794dc0f3d17b62cc28eb1f9461cb8cb [file] [log] [blame] [view]
mohammad160387a7eeb2018-11-01 11:25:49 +02001## Getting started with Mbed Crypto
2
3### What is Mbed Crypto?
4
5Mbed Crypto is an open source cryptographic library that supports a wide range of cryptographic operations, including:
6* Key management
7* Hashing
8* Symmetric cryptography
9* Asymmetric cryptography
10* Message authentication (MAC)
11* Key generation and derivation
12* Authenticated encryption with associated data (AEAD)
13
14The Mbed Crypto library is a reference implementation of the cryptography interface of the Arm Platform Security Architecture (PSA). It is written in portable C.
15
16The Mbed Crypto library is distributed under the Apache License, version 2.0.
17
18#### Platform Security Architecture (PSA)
19
20Arm's Platform Security Architecture (PSA) is a holistic set of threat models,
Guy Wildc03c0fc2019-09-03 13:18:04 +030021security analyses, hardware and firmware architecture specifications, and an open source firmware reference implementation. PSA provides a recipe, based on industry best practice, that enables you to design security into both hardware and firmware consistently. Part of the API provided by PSA is the cryptography interface, which provides access to a set of primitives.
mohammad160387a7eeb2018-11-01 11:25:49 +020022
23### Using Mbed Crypto
24
25* [Getting the Mbed Crypto library](#getting-the-mbed-crypto-library)
26* [Building the Mbed Crypto library](#building-the-mbed-crypto-library)
27* [Using the Mbed Crypto library](#using-the-mbed-crypto-library)
28* [Importing a key](#importing-a-key)
29* [Signing a message using RSA](#signing-a-message-using-RSA)
30* [Encrypting or decrypting using symmetric ciphers](#encrypting-or-decrypting-using-symmetric-ciphers)
31* [Hashing a message](#hashing-a-message)
32* [Deriving a new key from an existing key](#deriving-a-new-key-from-an-existing-key)
33* [Generating a random value](#generating-a-random-value)
34* [Authenticating and encrypting or decrypting a message](#authenticating-and-encrypting-or-decrypting-a-message)
35* [Generating and exporting keys](#generating-and-exporting-keys)
36* [More about the Mbed Crypto library](#more-about-the-mbed-crypto-library)
37
38### Getting the Mbed Crypto library
39
Guy Wildc03c0fc2019-09-03 13:18:04 +030040Mbed Crypto releases are available in the [public GitHub repository](https://github.com/ARMmbed/mbed-crypto).
mohammad160387a7eeb2018-11-01 11:25:49 +020041
42### Building the Mbed Crypto library
43
Guy Wildc03c0fc2019-09-03 13:18:04 +030044**Prerequisites to building the library with the provided makefiles:**
mohammad160387a7eeb2018-11-01 11:25:49 +020045* GNU Make.
46* A C toolchain (compiler, linker, archiver).
47* Python 2 or Python 3 (either works) to generate the test code.
48* Perl to run the tests.
49
Guy Wildc03c0fc2019-09-03 13:18:04 +030050If you have a C compiler, such as GCC or Clang, just run `make` in the top-level directory to build the library, a set of unit tests and some sample programs.
mohammad160387a7eeb2018-11-01 11:25:49 +020051
Guy Wildc03c0fc2019-09-03 13:18:04 +030052To select a different compiler, set the `CC` variable to the name or path of the compiler and linker (default: `cc`) and set `AR` to a compatible archiver (default: `ar`); for example:
mohammad160387a7eeb2018-11-01 11:25:49 +020053```
54make CC=arm-linux-gnueabi-gcc AR=arm-linux-gnueabi-ar
55```
56The provided makefiles pass options to the compiler that assume a GCC-like command line syntax. To use a different compiler, you may need to pass different values for `CFLAGS`, `WARNINGS_CFLAGS` and `LDFLAGS`.
57
58To run the unit tests on the host machine, run `make test` from the top-level directory. If you are cross-compiling, copy the test executable from the `tests` directory to the target machine.
59
60### Using the Mbed Crypto library
61
62To use the Mbed Crypto APIs, call `psa_crypto_init()` before calling any other API. This initializes the library.
63
64### Importing a key
65
Jaeden Amero884738a2019-08-16 17:58:31 +010066To use a key for cryptography operations in Mbed Crypto, you need to first
Guy Wildc03c0fc2019-09-03 13:18:04 +030067import it. After you import the key, you'll be given a handle that refers to the key for use
Jaeden Amero884738a2019-08-16 17:58:31 +010068with other function calls.
mohammad160387a7eeb2018-11-01 11:25:49 +020069
Guy Wildc03c0fc2019-09-03 13:18:04 +030070**Prerequisites for importing keys:**
71* Initialize the library with a successful call to `psa_crypto_init()`.
mohammad160387a7eeb2018-11-01 11:25:49 +020072
Guy Wildc03c0fc2019-09-03 13:18:04 +030073This example shows how to import a key:
mohammad160387a7eeb2018-11-01 11:25:49 +020074```C
Jaeden Amero884738a2019-08-16 17:58:31 +010075 psa_status_t status;
76 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
77 uint8_t data[] = AES_KEY;
78 psa_key_handle_t handle;
mohammad160387a7eeb2018-11-01 11:25:49 +020079
Jaeden Amero884738a2019-08-16 17:58:31 +010080 printf("Import an AES key...\t");
81 fflush(stdout);
82
83 /* Initialize PSA Crypto */
84 status = psa_crypto_init();
85 if (status != PSA_SUCCESS) {
86 printf("Failed to initialize PSA Crypto\n");
87 return;
88 }
89
90 /* Set key attributes */
91 psa_set_key_usage_flags(&attributes, 0);
92 psa_set_key_algorithm(&attributes, 0);
93 psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
94 psa_set_key_bits(&attributes, 128);
mohammad160387a7eeb2018-11-01 11:25:49 +020095
96 /* Import the key */
Jaeden Amero884738a2019-08-16 17:58:31 +010097 status = psa_import_key(&attributes, data, sizeof(data), &handle);
98 if (status != PSA_SUCCESS) {
99 printf("Failed to import key\n");
100 return;
101 }
102 printf("Imported a key\n");
mohammad160387a7eeb2018-11-01 11:25:49 +0200103
Jaeden Amero884738a2019-08-16 17:58:31 +0100104 /* Free the attributes */
105 psa_reset_key_attributes(&attributes);
mohammad160387a7eeb2018-11-01 11:25:49 +0200106
107 /* Destroy the key */
Jaeden Amero884738a2019-08-16 17:58:31 +0100108 psa_destroy_key(handle);
109
mohammad160387a7eeb2018-11-01 11:25:49 +0200110 mbedtls_psa_crypto_free();
111```
112
113### Signing a message using RSA
114
Guy Wildc03c0fc2019-09-03 13:18:04 +0300115Mbed Crypto supports encrypting, decrypting, signing and verifying messages using public key signature algorithms, such as RSA or ECDSA.
mohammad160387a7eeb2018-11-01 11:25:49 +0200116
Guy Wildc03c0fc2019-09-03 13:18:04 +0300117**Prerequisites to performing asymmetric signature operations:**
118* Initialize the library with a successful call to `psa_crypto_init()`.
Jaeden Amero884738a2019-08-16 17:58:31 +0100119* Have a valid key with appropriate attributes set:
120 * Usage flag `PSA_KEY_USAGE_SIGN` to allow signing.
121 * Usage flag `PSA_KEY_USAGE_VERIFY` to allow signature verification.
Guy Wildc03c0fc2019-09-03 13:18:04 +0300122 * Algorithm set to the desired signature algorithm.
mohammad160387a7eeb2018-11-01 11:25:49 +0200123
Guy Wildc03c0fc2019-09-03 13:18:04 +0300124This example shows how to sign a given hash using RSA, call `psa_asymmetric_sign()` and get the output buffer that contains the signature:
mohammad160387a7eeb2018-11-01 11:25:49 +0200125```C
126 psa_status_t status;
Jaeden Amero884738a2019-08-16 17:58:31 +0100127 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
128 uint8_t key[] = RSA_KEY;
129 uint8_t hash[] = "INPUT_FOR_SIGN";
130 uint8_t signature[PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE] = {0};
mohammad160387a7eeb2018-11-01 11:25:49 +0200131 size_t signature_length;
Jaeden Amero884738a2019-08-16 17:58:31 +0100132 psa_key_handle_t handle;
mohammad160387a7eeb2018-11-01 11:25:49 +0200133
Jaeden Amero884738a2019-08-16 17:58:31 +0100134 printf("Sign a message...\t");
135 fflush(stdout);
136
137 /* Initialize PSA Crypto */
mohammad160387a7eeb2018-11-01 11:25:49 +0200138 status = psa_crypto_init();
Jaeden Amero884738a2019-08-16 17:58:31 +0100139 if (status != PSA_SUCCESS) {
140 printf("Failed to initialize PSA Crypto\n");
141 return;
142 }
143
144 /* Set key attributes */
145 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN);
146 psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_SIGN_RAW);
147 psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR);
148 psa_set_key_bits(&attributes, 1024);
mohammad160387a7eeb2018-11-01 11:25:49 +0200149
150 /* Import the key */
Jaeden Amero884738a2019-08-16 17:58:31 +0100151 status = psa_import_key(&attributes, key, sizeof(key), &handle);
152 if (status != PSA_SUCCESS) {
153 printf("Failed to import key\n");
154 return;
155 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200156
Jaeden Amero884738a2019-08-16 17:58:31 +0100157 /* Sign message using the key */
158 status = psa_asymmetric_sign(handle, PSA_ALG_RSA_PKCS1V15_SIGN_RAW,
159 hash, sizeof(hash),
mohammad160387a7eeb2018-11-01 11:25:49 +0200160 signature, sizeof(signature),
161 &signature_length);
Jaeden Amero884738a2019-08-16 17:58:31 +0100162 if (status != PSA_SUCCESS) {
163 printf("Failed to sign\n");
164 return;
165 }
166
167 printf("Signed a message\n");
168
169 /* Free the attributes */
170 psa_reset_key_attributes(&attributes);
171
mohammad160387a7eeb2018-11-01 11:25:49 +0200172 /* Destroy the key */
Jaeden Amero884738a2019-08-16 17:58:31 +0100173 psa_destroy_key(handle);
174
mohammad160387a7eeb2018-11-01 11:25:49 +0200175 mbedtls_psa_crypto_free();
176```
177
Jaeden Amero884738a2019-08-16 17:58:31 +0100178### Using symmetric ciphers
mohammad160387a7eeb2018-11-01 11:25:49 +0200179
Guy Wildc03c0fc2019-09-03 13:18:04 +0300180Mbed Crypto supports encrypting and decrypting messages using various symmetric cipher algorithms (both block and stream ciphers).
mohammad160387a7eeb2018-11-01 11:25:49 +0200181
Guy Wildc03c0fc2019-09-03 13:18:04 +0300182**Prerequisites to working with the symmetric cipher API:**
183* Initialize the library with a successful call to `psa_crypto_init()`.
184* Configure the key policy accordingly (set `PSA_KEY_USAGE_ENCRYPT` to allow encryption or `PSA_KEY_USAGE_DECRYPT` to allow decryption).
mohammad160387a7eeb2018-11-01 11:25:49 +0200185* Have a valid key in the key slot.
186
Guy Wildc03c0fc2019-09-03 13:18:04 +0300187**To encrypt a message with a symmetric cipher:**
mohammad160387a7eeb2018-11-01 11:25:49 +02001881. Allocate an operation (`psa_cipher_operation_t`) structure to pass to the cipher functions.
Guy Wildc03c0fc2019-09-03 13:18:04 +03001891. Call `psa_cipher_encrypt_setup()` to initialize the operation structure and specify the algorithm and the key to be used.
1901. Call either `psa_cipher_generate_iv()` or `psa_cipher_set_iv()` to generate or set the initialization vector (IV). We recommended calling `psa_cipher_generate_iv()`, unless you require a specific IV value.
1911. Call `psa_cipher_update()` one or more times, passing the whole message or only a fragment of the message each time.
1921. Call `psa_cipher_finish()` to end the operation and output the encrypted message.
mohammad160387a7eeb2018-11-01 11:25:49 +0200193
Guy Wildc03c0fc2019-09-03 13:18:04 +0300194This example shows how to encrypt data using an Advanced Encryption Standard (AES) key in cipher block chain (CBC) mode with no padding (assuming all prerequisites have been fulfilled):
mohammad160387a7eeb2018-11-01 11:25:49 +0200195```c
Jaeden Amero884738a2019-08-16 17:58:31 +0100196 enum {
197 block_size = PSA_BLOCK_CIPHER_BLOCK_SIZE(PSA_KEY_TYPE_AES),
198 };
199 psa_status_t status;
200 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
mohammad160387a7eeb2018-11-01 11:25:49 +0200201 psa_algorithm_t alg = PSA_ALG_CBC_NO_PADDING;
Jaeden Amero884738a2019-08-16 17:58:31 +0100202 uint8_t plaintext[block_size] = SOME_PLAINTEXT;
203 uint8_t iv[block_size];
mohammad160387a7eeb2018-11-01 11:25:49 +0200204 size_t iv_len;
Jaeden Amero884738a2019-08-16 17:58:31 +0100205 uint8_t key[] = AES_KEY;
206 uint8_t output[block_size];
mohammad160387a7eeb2018-11-01 11:25:49 +0200207 size_t output_len;
Jaeden Amero884738a2019-08-16 17:58:31 +0100208 psa_key_handle_t handle;
209 psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
mohammad160387a7eeb2018-11-01 11:25:49 +0200210
Jaeden Amero884738a2019-08-16 17:58:31 +0100211 printf("Encrypt with cipher...\t");
212 fflush(stdout);
mohammad160387a7eeb2018-11-01 11:25:49 +0200213
Jaeden Amero884738a2019-08-16 17:58:31 +0100214 /* Initialize PSA Crypto */
215 status = psa_crypto_init();
216 if (status != PSA_SUCCESS)
217 {
218 printf("Failed to initialize PSA Crypto\n");
219 return;
220 }
221
222 /* Import a key */
223 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
224 psa_set_key_algorithm(&attributes, alg);
225 psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
226 psa_set_key_bits(&attributes, 128);
227 status = psa_import_key(&attributes, key, sizeof(key), &handle);
228 if (status != PSA_SUCCESS) {
229 printf("Failed to import a key\n");
230 return;
231 }
232 psa_reset_key_attributes(&attributes);
233
234 /* Encrypt the plaintext */
235 status = psa_cipher_encrypt_setup(&operation, handle, alg);
236 if (status != PSA_SUCCESS) {
237 printf("Failed to begin cipher operation\n");
238 return;
239 }
240 status = psa_cipher_generate_iv(&operation, iv, sizeof(iv), &iv_len);
241 if (status != PSA_SUCCESS) {
242 printf("Failed to generate IV\n");
243 return;
244 }
245 status = psa_cipher_update(&operation, plaintext, sizeof(plaintext),
246 output, sizeof(output), &output_len);
247 if (status != PSA_SUCCESS) {
248 printf("Failed to update cipher operation\n");
249 return;
250 }
251 status = psa_cipher_finish(&operation, output + output_len,
252 sizeof(output) - output_len, &output_len);
253 if (status != PSA_SUCCESS) {
254 printf("Failed to finish cipher operation\n");
255 return;
256 }
257 printf("Encrypted plaintext\n");
258
mohammad160387a7eeb2018-11-01 11:25:49 +0200259 /* Clean up cipher operation context */
260 psa_cipher_abort(&operation);
Jaeden Amero884738a2019-08-16 17:58:31 +0100261
262 /* Destroy the key */
263 psa_destroy_key(handle);
264
265 mbedtls_psa_crypto_free();
mohammad160387a7eeb2018-11-01 11:25:49 +0200266```
267
Guy Wildc03c0fc2019-09-03 13:18:04 +0300268**To decrypt a message with a symmetric cipher:**
mohammad160387a7eeb2018-11-01 11:25:49 +02002691. Allocate an operation (`psa_cipher_operation_t`) structure to pass to the cipher functions.
Guy Wildc03c0fc2019-09-03 13:18:04 +03002701. Call `psa_cipher_decrypt_setup()` to initialize the operation structure and to specify the algorithm and the key to be used.
2711. Call `psa_cipher_set_iv()` with the IV for the decryption.
2721. Call `psa_cipher_update()` one or more times, passing the whole message or only a fragment of the message each time.
2731. Call `psa_cipher_finish()` to end the operation and output the decrypted message.
mohammad160387a7eeb2018-11-01 11:25:49 +0200274
Guy Wildc03c0fc2019-09-03 13:18:04 +0300275This example shows how to decrypt encrypted data using an AES key in CBC mode with no padding
mohammad160387a7eeb2018-11-01 11:25:49 +0200276(assuming all prerequisites have been fulfilled):
277```c
Jaeden Amero884738a2019-08-16 17:58:31 +0100278 enum {
279 block_size = PSA_BLOCK_CIPHER_BLOCK_SIZE(PSA_KEY_TYPE_AES),
280 };
281 psa_status_t status;
282 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
mohammad160387a7eeb2018-11-01 11:25:49 +0200283 psa_algorithm_t alg = PSA_ALG_CBC_NO_PADDING;
Jaeden Amero884738a2019-08-16 17:58:31 +0100284 psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
285 uint8_t ciphertext[block_size] = SOME_CIPHERTEXT;
286 uint8_t iv[block_size] = ENCRYPTED_WITH_IV;
287 uint8_t key[] = AES_KEY;
288 uint8_t output[block_size];
mohammad160387a7eeb2018-11-01 11:25:49 +0200289 size_t output_len;
Jaeden Amero884738a2019-08-16 17:58:31 +0100290 psa_key_handle_t handle;
mohammad160387a7eeb2018-11-01 11:25:49 +0200291
Jaeden Amero884738a2019-08-16 17:58:31 +0100292 printf("Decrypt with cipher...\t");
293 fflush(stdout);
mohammad160387a7eeb2018-11-01 11:25:49 +0200294
Jaeden Amero884738a2019-08-16 17:58:31 +0100295 /* Initialize PSA Crypto */
296 status = psa_crypto_init();
297 if (status != PSA_SUCCESS)
298 {
299 printf("Failed to initialize PSA Crypto\n");
300 return;
301 }
302
303 /* Import a key */
304 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT);
305 psa_set_key_algorithm(&attributes, alg);
306 psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
307 psa_set_key_bits(&attributes, 128);
308 status = psa_import_key(&attributes, key, sizeof(key), &handle);
309 if (status != PSA_SUCCESS) {
310 printf("Failed to import a key\n");
311 return;
312 }
313 psa_reset_key_attributes(&attributes);
314
315 /* Decrypt the ciphertext */
316 status = psa_cipher_decrypt_setup(&operation, handle, alg);
317 if (status != PSA_SUCCESS) {
318 printf("Failed to begin cipher operation\n");
319 return;
320 }
321 status = psa_cipher_set_iv(&operation, iv, sizeof(iv));
322 if (status != PSA_SUCCESS) {
323 printf("Failed to set IV\n");
324 return;
325 }
326 status = psa_cipher_update(&operation, ciphertext, sizeof(ciphertext),
327 output, sizeof(output), &output_len);
328 if (status != PSA_SUCCESS) {
329 printf("Failed to update cipher operation\n");
330 return;
331 }
332 status = psa_cipher_finish(&operation, output + output_len,
333 sizeof(output) - output_len, &output_len);
334 if (status != PSA_SUCCESS) {
335 printf("Failed to finish cipher operation\n");
336 return;
337 }
338 printf("Decrypted ciphertext\n");
339
mohammad160387a7eeb2018-11-01 11:25:49 +0200340 /* Clean up cipher operation context */
341 psa_cipher_abort(&operation);
Jaeden Amero884738a2019-08-16 17:58:31 +0100342
343 /* Destroy the key */
344 psa_destroy_key(handle);
345
346 mbedtls_psa_crypto_free();
mohammad160387a7eeb2018-11-01 11:25:49 +0200347```
348
349#### Handling cipher operation contexts
350
Guy Wildc03c0fc2019-09-03 13:18:04 +0300351After you've initialized the operation structure with a successful call to `psa_cipher_encrypt_setup()` or `psa_cipher_decrypt_setup()`, you can terminate the operation at any time by calling `psa_cipher_abort()`.
mohammad160387a7eeb2018-11-01 11:25:49 +0200352
Guy Wildc03c0fc2019-09-03 13:18:04 +0300353The call to `psa_cipher_abort()` frees any resources associated with the operation, except for the operation structure itself.
mohammad160387a7eeb2018-11-01 11:25:49 +0200354
Guy Wildc03c0fc2019-09-03 13:18:04 +0300355Mbed Crypto implicitly calls `psa_cipher_abort()` when:
356* A call to `psa_cipher_generate_iv()`, `psa_cipher_set_iv()` or `psa_cipher_update()` fails (returning any status other than `PSA_SUCCESS`).
357* A call to `psa_cipher_finish()` succeeds or fails.
mohammad160387a7eeb2018-11-01 11:25:49 +0200358
Guy Wildc03c0fc2019-09-03 13:18:04 +0300359After an implicit or explicit call to `psa_cipher_abort()`, the operation structure is invalidated; in other words, you cannot reuse the operation structure for the same operation. You can, however, reuse the operation structure for a different operation by calling either `psa_cipher_encrypt_setup()` or `psa_cipher_decrypt_setup()` again.
mohammad160387a7eeb2018-11-01 11:25:49 +0200360
Guy Wildc03c0fc2019-09-03 13:18:04 +0300361You must call `psa_cipher_abort()` at some point for any operation that is initialized successfully (by a successful call to `psa_cipher_encrypt_setup()` or `psa_cipher_decrypt_setup()`).
362
363Making multiple sequential calls to `psa_cipher_abort()` on an operation that is terminated (either implicitly or explicitly) is safe and has no effect.
mohammad160387a7eeb2018-11-01 11:25:49 +0200364
365### Hashing a message
366
Jaeden Amero884738a2019-08-16 17:58:31 +0100367Mbed Crypto lets you compute and verify hashes using various hashing
368algorithms.
mohammad160387a7eeb2018-11-01 11:25:49 +0200369
Guy Wildc03c0fc2019-09-03 13:18:04 +0300370**Prerequisites to working with the hash APIs:**
371* Initialize the library with a successful call to `psa_crypto_init()`.
mohammad160387a7eeb2018-11-01 11:25:49 +0200372
Guy Wildc03c0fc2019-09-03 13:18:04 +0300373**To calculate a hash:**
mohammad160387a7eeb2018-11-01 11:25:49 +02003741. Allocate an operation structure (`psa_hash_operation_t`) to pass to the hash functions.
Guy Wildc03c0fc2019-09-03 13:18:04 +03003751. Call `psa_hash_setup()` to initialize the operation structure and specify the hash algorithm.
3761. Call `psa_hash_update()` one or more times, passing the whole message or only a fragment of the message each time.
3771. Call `psa_hash_finish()` to calculate the hash, or `psa_hash_verify()` to compare the computed hash with an expected hash value.
mohammad160387a7eeb2018-11-01 11:25:49 +0200378
Guy Wildc03c0fc2019-09-03 13:18:04 +0300379This example shows how to calculate the `SHA-256` hash of a message:
mohammad160387a7eeb2018-11-01 11:25:49 +0200380```c
Jaeden Amero884738a2019-08-16 17:58:31 +0100381 psa_status_t status;
mohammad160387a7eeb2018-11-01 11:25:49 +0200382 psa_algorithm_t alg = PSA_ALG_SHA_256;
Jaeden Amero884738a2019-08-16 17:58:31 +0100383 psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
mohammad160387a7eeb2018-11-01 11:25:49 +0200384 unsigned char input[] = { 'a', 'b', 'c' };
385 unsigned char actual_hash[PSA_HASH_MAX_SIZE];
386 size_t actual_hash_len;
387
Jaeden Amero884738a2019-08-16 17:58:31 +0100388 printf("Hash a message...\t");
389 fflush(stdout);
390
391 /* Initialize PSA Crypto */
392 status = psa_crypto_init();
393 if (status != PSA_SUCCESS) {
394 printf("Failed to initialize PSA Crypto\n");
395 return;
396 }
397
mohammad160387a7eeb2018-11-01 11:25:49 +0200398 /* Compute hash of message */
Jaeden Amero884738a2019-08-16 17:58:31 +0100399 status = psa_hash_setup(&operation, alg);
400 if (status != PSA_SUCCESS) {
401 printf("Failed to begin hash operation\n");
402 return;
403 }
404 status = psa_hash_update(&operation, input, sizeof(input));
405 if (status != PSA_SUCCESS) {
406 printf("Failed to update hash operation\n");
407 return;
408 }
409 status = psa_hash_finish(&operation, actual_hash, sizeof(actual_hash),
410 &actual_hash_len);
411 if (status != PSA_SUCCESS) {
412 printf("Failed to finish hash operation\n");
413 return;
414 }
415
416 printf("Hashed a message\n");
mohammad160387a7eeb2018-11-01 11:25:49 +0200417
418 /* Clean up hash operation context */
419 psa_hash_abort(&operation);
Jaeden Amero884738a2019-08-16 17:58:31 +0100420
421 mbedtls_psa_crypto_free();
mohammad160387a7eeb2018-11-01 11:25:49 +0200422```
423
Guy Wildc03c0fc2019-09-03 13:18:04 +0300424This example shows how to verify the `SHA-256` hash of a message:
mohammad160387a7eeb2018-11-01 11:25:49 +0200425```c
Jaeden Amero884738a2019-08-16 17:58:31 +0100426 psa_status_t status;
mohammad160387a7eeb2018-11-01 11:25:49 +0200427 psa_algorithm_t alg = PSA_ALG_SHA_256;
Jaeden Amero884738a2019-08-16 17:58:31 +0100428 psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
mohammad160387a7eeb2018-11-01 11:25:49 +0200429 unsigned char input[] = { 'a', 'b', 'c' };
430 unsigned char expected_hash[] = {
431 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, 0xde,
432 0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
433 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad
434 };
435 size_t expected_hash_len = PSA_HASH_SIZE(alg);
436
Jaeden Amero884738a2019-08-16 17:58:31 +0100437 printf("Verify a hash...\t");
438 fflush(stdout);
439
440 /* Initialize PSA Crypto */
441 status = psa_crypto_init();
442 if (status != PSA_SUCCESS) {
443 printf("Failed to initialize PSA Crypto\n");
444 return;
445 }
446
mohammad160387a7eeb2018-11-01 11:25:49 +0200447 /* Verify message hash */
Jaeden Amero884738a2019-08-16 17:58:31 +0100448 status = psa_hash_setup(&operation, alg);
449 if (status != PSA_SUCCESS) {
450 printf("Failed to begin hash operation\n");
451 return;
452 }
453 status = psa_hash_update(&operation, input, sizeof(input));
454 if (status != PSA_SUCCESS) {
455 printf("Failed to update hash operation\n");
456 return;
457 }
458 status = psa_hash_verify(&operation, expected_hash, expected_hash_len);
459 if (status != PSA_SUCCESS) {
460 printf("Failed to verify hash\n");
461 return;
462 }
463
464 printf("Verified a hash\n");
465
466 /* Clean up hash operation context */
467 psa_hash_abort(&operation);
468
469 mbedtls_psa_crypto_free();
mohammad160387a7eeb2018-11-01 11:25:49 +0200470```
471
472The API provides the macro `PSA_HASH_SIZE`, which returns the expected hash length (in bytes) for the specified algorithm.
473
474#### Handling hash operation contexts
475
Guy Wildc03c0fc2019-09-03 13:18:04 +0300476After a successful call to `psa_hash_setup()` initializes the operation structure, you can terminate the operation at any time by calling `psa_hash_abort()`. The call to `psa_hash_abort()` frees any resources associated with the operation, except for the operation structure itself.
mohammad160387a7eeb2018-11-01 11:25:49 +0200477
Guy Wildc03c0fc2019-09-03 13:18:04 +0300478Mbed Crypto implicitly calls `psa_hash_abort()` when:
4791. A call to `psa_hash_update()` fails (returning any status other than `PSA_SUCCESS`).
4801. A call to `psa_hash_finish()` succeeds or fails.
4811. A call to `psa_hash_verify()` succeeds or fails.
mohammad160387a7eeb2018-11-01 11:25:49 +0200482
Guy Wildc03c0fc2019-09-03 13:18:04 +0300483After an implicit or explicit call to `psa_hash_abort()`, the operation structure is invalidated; in other words, you cannot reuse the operation structure for the same operation. You can, however, reuse the operation structure for a different operation by calling `psa_hash_setup()` again.
mohammad160387a7eeb2018-11-01 11:25:49 +0200484
Guy Wildc03c0fc2019-09-03 13:18:04 +0300485You must call `psa_hash_abort()` at some point for any operation that is initialized successfully (by a successful call to `psa_hash_setup()`) .
mohammad160387a7eeb2018-11-01 11:25:49 +0200486
Guy Wildc03c0fc2019-09-03 13:18:04 +0300487Making multiple sequential calls to `psa_hash_abort()` on an operation that has already been terminated (either implicitly or explicitly) is safe and has no effect.
mohammad160387a7eeb2018-11-01 11:25:49 +0200488
489### Generating a random value
490
Guy Wildc03c0fc2019-09-03 13:18:04 +0300491Mbed Crypto can generate random data.
mohammad160387a7eeb2018-11-01 11:25:49 +0200492
Guy Wildc03c0fc2019-09-03 13:18:04 +0300493**Prerequisites to random generation:**
Jaeden Amero884738a2019-08-16 17:58:31 +0100494* Initialize the library with a successful call to `psa_crypto_init()`.
mohammad160387a7eeb2018-11-01 11:25:49 +0200495
Guy Wildc03c0fc2019-09-03 13:18:04 +0300496This example shows how to generate a random, ten-byte piece of data by calling `psa_generate_random()`:
mohammad160387a7eeb2018-11-01 11:25:49 +0200497```C
498 psa_status_t status;
499 uint8_t random[10] = { 0 };
mohammad160387a7eeb2018-11-01 11:25:49 +0200500
Jaeden Amero884738a2019-08-16 17:58:31 +0100501 printf("Generate random...\t");
502 fflush(stdout);
503
504 /* Initialize PSA Crypto */
505 status = psa_crypto_init();
506 if (status != PSA_SUCCESS) {
507 printf("Failed to initialize PSA Crypto\n");
508 return;
509 }
510
511 status = psa_generate_random(random, sizeof(random));
512 if (status != PSA_SUCCESS) {
513 printf("Failed to generate a random value\n");
514 return;
515 }
516
517 printf("Generated random data\n");
518
519 /* Clean up */
mohammad160387a7eeb2018-11-01 11:25:49 +0200520 mbedtls_psa_crypto_free();
521```
Guy Wildc03c0fc2019-09-03 13:18:04 +0300522To generate a random key, use `psa_generate_key()` instead of `psa_generate_random()`.
mohammad160387a7eeb2018-11-01 11:25:49 +0200523
524### Deriving a new key from an existing key
525
Jaeden Amero884738a2019-08-16 17:58:31 +0100526Mbed Crypto provides a key derivation API that lets you derive new keys from
527existing ones. The key derivation API has functions to take inputs, including
528other keys and data, and functions to generate outputs, such as new keys or
Guy Wildc03c0fc2019-09-03 13:18:04 +0300529other data.
mohammad160387a7eeb2018-11-01 11:25:49 +0200530
Guy Wildc03c0fc2019-09-03 13:18:04 +0300531You must first initialize and set up a key derivation context,
532provided with a key and, optionally, other data. Then, use the key derivation context to either read derived data to a buffer or send derived data directly to a key slot.
533
534See the documentation for the particular algorithm (such as HKDF or the TLS1.2 PRF) for
535information about which inputs to pass when, and when you can obtain which outputs.
536
537**Prerequisites to working with the key derivation APIs:**
538* Initialize the library with a successful call to `psa_crypto_init()`.
Jaeden Amero884738a2019-08-16 17:58:31 +0100539* Use a key with the appropriate attributes set:
540 * Usage flags set for key derivation (`PSA_KEY_USAGE_DERIVE`)
541 * Key type set to `PSA_KEY_TYPE_DERIVE`.
542 * Algorithm set to a key derivation algorithm
543 (`PSA_ALG_HKDF(PSA_ALG_SHA_256)`).
mohammad160387a7eeb2018-11-01 11:25:49 +0200544
Guy Wildc03c0fc2019-09-03 13:18:04 +0300545**To derive a new AES-CTR 128-bit encryption key into a given key slot using HKDF
546with a given key, salt and information:**
547
5481. Set up the key derivation context using the `psa_key_derivation_setup()`
Jaeden Amero884738a2019-08-16 17:58:31 +0100549function, specifying the derivation algorithm `PSA_ALG_HKDF(PSA_ALG_SHA_256)`.
Guy Wildc03c0fc2019-09-03 13:18:04 +03005501. Provide an optional salt with `psa_key_derivation_input_bytes()`.
5511. Provide information with `psa_key_derivation_input_bytes()`.
5521. Provide a secret with `psa_key_derivation_input_key()`, referencing a key that
Jaeden Amero884738a2019-08-16 17:58:31 +0100553 can be used for key derivation.
5541. Set the key attributes desired for the new derived key. We'll set
Guy Wildc03c0fc2019-09-03 13:18:04 +0300555 the `PSA_KEY_USAGE_ENCRYPT` parameter and the `PSA_ALG_CTR` algorithm for this
Jaeden Amero884738a2019-08-16 17:58:31 +0100556 example.
5571. Derive the key by calling `psa_key_derivation_output_key()`.
5581. Clean up the key derivation context.
mohammad160387a7eeb2018-11-01 11:25:49 +0200559
Guy Wildc03c0fc2019-09-03 13:18:04 +0300560At this point, the derived key slot holds a new 128-bit AES-CTR encryption key
561derived from the key, salt and information provided:
mohammad160387a7eeb2018-11-01 11:25:49 +0200562```C
Jaeden Amero884738a2019-08-16 17:58:31 +0100563 psa_status_t status;
564 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
565 static const unsigned char key[] = {
mohammad160387a7eeb2018-11-01 11:25:49 +0200566 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
567 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
568 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
569 0x0b };
Jaeden Amero884738a2019-08-16 17:58:31 +0100570 static const unsigned char salt[] = {
571 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
572 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c };
573 static const unsigned char info[] = {
574 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6,
575 0xf7, 0xf8, 0xf9 };
mohammad160387a7eeb2018-11-01 11:25:49 +0200576 psa_algorithm_t alg = PSA_ALG_HKDF(PSA_ALG_SHA_256);
Jaeden Amero884738a2019-08-16 17:58:31 +0100577 psa_key_derivation_operation_t operation =
578 PSA_KEY_DERIVATION_OPERATION_INIT;
mohammad160387a7eeb2018-11-01 11:25:49 +0200579 size_t derived_bits = 128;
580 size_t capacity = PSA_BITS_TO_BYTES(derived_bits);
Jaeden Amero884738a2019-08-16 17:58:31 +0100581 psa_key_handle_t base_key;
582 psa_key_handle_t derived_key;
mohammad160387a7eeb2018-11-01 11:25:49 +0200583
Jaeden Amero884738a2019-08-16 17:58:31 +0100584 printf("Derive a key (HKDF)...\t");
585 fflush(stdout);
586
587 /* Initialize PSA Crypto */
mohammad160387a7eeb2018-11-01 11:25:49 +0200588 status = psa_crypto_init();
Jaeden Amero884738a2019-08-16 17:58:31 +0100589 if (status != PSA_SUCCESS) {
590 printf("Failed to initialize PSA Crypto\n");
591 return;
592 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200593
Jaeden Amero884738a2019-08-16 17:58:31 +0100594 /* Import a key for use in key derivation. If such a key has already been
595 * generated or imported, you can skip this part. */
596 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE);
597 psa_set_key_algorithm(&attributes, alg);
598 psa_set_key_type(&attributes, PSA_KEY_TYPE_DERIVE);
599 status = psa_import_key(&attributes, key, sizeof(key), &base_key);
600 if (status != PSA_SUCCESS) {
601 printf("Failed to import a key\n");
602 return;
603 }
604 psa_reset_key_attributes(&attributes);
mohammad160387a7eeb2018-11-01 11:25:49 +0200605
Jaeden Amero884738a2019-08-16 17:58:31 +0100606 /* Derive a key */
607 status = psa_key_derivation_setup(&operation, alg);
608 if (status != PSA_SUCCESS) {
609 printf("Failed to begin key derivation\n");
610 return;
611 }
612 status = psa_key_derivation_set_capacity(&operation, capacity);
613 if (status != PSA_SUCCESS) {
614 printf("Failed to set capacity\n");
615 return;
616 }
617 status = psa_key_derivation_input_bytes(&operation,
618 PSA_KEY_DERIVATION_INPUT_SALT,
619 salt, sizeof(salt));
620 if (status != PSA_SUCCESS) {
621 printf("Failed to input salt (extract)\n");
622 return;
623 }
624 status = psa_key_derivation_input_key(&operation,
625 PSA_KEY_DERIVATION_INPUT_SECRET,
626 base_key);
627 if (status != PSA_SUCCESS) {
628 printf("Failed to input key (extract)\n");
629 return;
630 }
631 status = psa_key_derivation_input_bytes(&operation,
632 PSA_KEY_DERIVATION_INPUT_INFO,
633 info, sizeof(info));
634 if (status != PSA_SUCCESS) {
635 printf("Failed to input info (expand)\n");
636 return;
637 }
638 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
639 psa_set_key_algorithm(&attributes, PSA_ALG_CTR);
640 psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
641 psa_set_key_bits(&attributes, 128);
642 status = psa_key_derivation_output_key(&attributes, &operation,
643 &derived_key);
644 if (status != PSA_SUCCESS) {
645 printf("Failed to derive key\n");
646 return;
647 }
648 psa_reset_key_attributes(&attributes);
mohammad160387a7eeb2018-11-01 11:25:49 +0200649
Jaeden Amero884738a2019-08-16 17:58:31 +0100650 printf("Derived key\n");
mohammad160387a7eeb2018-11-01 11:25:49 +0200651
Jaeden Amero884738a2019-08-16 17:58:31 +0100652 /* Clean up key derivation operation */
653 psa_key_derivation_abort(&operation);
mohammad160387a7eeb2018-11-01 11:25:49 +0200654
Jaeden Amero884738a2019-08-16 17:58:31 +0100655 /* Destroy the keys */
656 psa_destroy_key(derived_key);
657 psa_destroy_key(base_key);
mohammad160387a7eeb2018-11-01 11:25:49 +0200658
mohammad160387a7eeb2018-11-01 11:25:49 +0200659 mbedtls_psa_crypto_free();
660```
661
662### Authenticating and encrypting or decrypting a message
663
Guy Wildc03c0fc2019-09-03 13:18:04 +0300664Mbed Crypto provides a simple way to authenticate and encrypt with associated data (AEAD), supporting the `PSA_ALG_CCM` algorithm.
mohammad160387a7eeb2018-11-01 11:25:49 +0200665
Guy Wildc03c0fc2019-09-03 13:18:04 +0300666**Prerequisites to working with the AEAD cipher APIs:**
667* Initialize the library with a successful call to `psa_crypto_init()`.
668* The key attributes for the key used for derivation must have the `PSA_KEY_USAGE_ENCRYPT` or `PSA_KEY_USAGE_DECRYPT` usage flags.
mohammad160387a7eeb2018-11-01 11:25:49 +0200669
Guy Wildc03c0fc2019-09-03 13:18:04 +0300670This example shows how to authenticate and encrypt a message:
mohammad160387a7eeb2018-11-01 11:25:49 +0200671```C
mohammad160387a7eeb2018-11-01 11:25:49 +0200672 psa_status_t status;
Jaeden Amero884738a2019-08-16 17:58:31 +0100673 static const uint8_t key[] = {
674 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
675 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF };
676 static const uint8_t nonce[] = {
677 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
678 0x08, 0x09, 0x0A, 0x0B };
679 static const uint8_t additional_data[] = {
680 0xEC, 0x46, 0xBB, 0x63, 0xB0, 0x25,
681 0x20, 0xC3, 0x3C, 0x49, 0xFD, 0x70 };
682 static const uint8_t input_data[] = {
683 0xB9, 0x6B, 0x49, 0xE2, 0x1D, 0x62, 0x17, 0x41,
684 0x63, 0x28, 0x75, 0xDB, 0x7F, 0x6C, 0x92, 0x43,
685 0xD2, 0xD7, 0xC2 };
686 uint8_t *output_data = NULL;
mohammad160387a7eeb2018-11-01 11:25:49 +0200687 size_t output_size = 0;
688 size_t output_length = 0;
689 size_t tag_length = 16;
Jaeden Amero884738a2019-08-16 17:58:31 +0100690 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
691 psa_key_handle_t handle;
692
693 printf("Authenticate encrypt...\t");
694 fflush(stdout);
695
696 /* Initialize PSA Crypto */
697 status = psa_crypto_init();
698 if (status != PSA_SUCCESS) {
699 printf("Failed to initialize PSA Crypto\n");
700 return;
701 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200702
703 output_size = sizeof(input_data) + tag_length;
Jaeden Amero884738a2019-08-16 17:58:31 +0100704 output_data = (uint8_t *)malloc(output_size);
705 if (!output_data) {
706 printf("Out of memory\n");
707 return;
708 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200709
Jaeden Amero884738a2019-08-16 17:58:31 +0100710 /* Import a key */
711 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
712 psa_set_key_algorithm(&attributes, PSA_ALG_CCM);
713 psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
714 psa_set_key_bits(&attributes, 128);
715 status = psa_import_key(&attributes, key, sizeof(key), &handle);
716 psa_reset_key_attributes(&attributes);
mohammad160387a7eeb2018-11-01 11:25:49 +0200717
Jaeden Amero884738a2019-08-16 17:58:31 +0100718 /* Authenticate and encrypt */
719 status = psa_aead_encrypt(handle, PSA_ALG_CCM,
mohammad160387a7eeb2018-11-01 11:25:49 +0200720 nonce, sizeof(nonce),
721 additional_data, sizeof(additional_data),
722 input_data, sizeof(input_data),
723 output_data, output_size,
724 &output_length);
Jaeden Amero884738a2019-08-16 17:58:31 +0100725 if (status != PSA_SUCCESS) {
726 printf("Failed to authenticate and encrypt\n");
727 return;
728 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200729
Jaeden Amero884738a2019-08-16 17:58:31 +0100730 printf("Authenticated and encrypted\n");
731
732 /* Clean up */
733 free(output_data);
734
735 /* Destroy the key */
736 psa_destroy_key(handle);
737
mohammad160387a7eeb2018-11-01 11:25:49 +0200738 mbedtls_psa_crypto_free();
739```
740
Guy Wildc03c0fc2019-09-03 13:18:04 +0300741This example shows how to authenticate and decrypt a message:
mohammad160387a7eeb2018-11-01 11:25:49 +0200742
743```C
mohammad160387a7eeb2018-11-01 11:25:49 +0200744 psa_status_t status;
Jaeden Amero884738a2019-08-16 17:58:31 +0100745 static const uint8_t key[] = {
mohammad160387a7eeb2018-11-01 11:25:49 +0200746 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
Jaeden Amero884738a2019-08-16 17:58:31 +0100747 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF };
748 static const uint8_t nonce[] = {
749 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
750 0x08, 0x09, 0x0A, 0x0B };
751 static const uint8_t additional_data[] = {
752 0xEC, 0x46, 0xBB, 0x63, 0xB0, 0x25,
753 0x20, 0xC3, 0x3C, 0x49, 0xFD, 0x70 };
754 static const uint8_t input_data[] = {
755 0x20, 0x30, 0xE0, 0x36, 0xED, 0x09, 0xA0, 0x45, 0xAF, 0x3C, 0xBA, 0xEE,
756 0x0F, 0xC8, 0x48, 0xAF, 0xCD, 0x89, 0x54, 0xF4, 0xF6, 0x3F, 0x28, 0x9A,
757 0xA1, 0xDD, 0xB2, 0xB8, 0x09, 0xCD, 0x7C, 0xE1, 0x46, 0xE9, 0x98 };
758 uint8_t *output_data = NULL;
mohammad160387a7eeb2018-11-01 11:25:49 +0200759 size_t output_size = 0;
760 size_t output_length = 0;
Jaeden Amero884738a2019-08-16 17:58:31 +0100761 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
762 psa_key_handle_t handle;
763
764 printf("Authenticate decrypt...\t");
765 fflush(stdout);
766
767 /* Initialize PSA Crypto */
768 status = psa_crypto_init();
769 if (status != PSA_SUCCESS) {
770 printf("Failed to initialize PSA Crypto\n");
771 return;
772 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200773
774 output_size = sizeof(input_data);
Jaeden Amero884738a2019-08-16 17:58:31 +0100775 output_data = (uint8_t *)malloc(output_size);
776 if (!output_data) {
777 printf("Out of memory\n");
778 return;
779 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200780
Jaeden Amero884738a2019-08-16 17:58:31 +0100781 /* Import a key */
782 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT);
783 psa_set_key_algorithm(&attributes, PSA_ALG_CCM);
784 psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
785 psa_set_key_bits(&attributes, 128);
786 status = psa_import_key(&attributes, key, sizeof(key), &handle);
787 if (status != PSA_SUCCESS) {
788 printf("Failed to import a key\n");
789 return;
790 }
791 psa_reset_key_attributes(&attributes);
mohammad160387a7eeb2018-11-01 11:25:49 +0200792
Jaeden Amero884738a2019-08-16 17:58:31 +0100793 /* Authenticate and decrypt */
794 status = psa_aead_decrypt(handle, PSA_ALG_CCM,
mohammad160387a7eeb2018-11-01 11:25:49 +0200795 nonce, sizeof(nonce),
796 additional_data, sizeof(additional_data),
797 input_data, sizeof(input_data),
798 output_data, output_size,
799 &output_length);
Jaeden Amero884738a2019-08-16 17:58:31 +0100800 if (status != PSA_SUCCESS) {
801 printf("Failed to authenticate and decrypt %ld\n", status);
802 return;
803 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200804
Jaeden Amero884738a2019-08-16 17:58:31 +0100805 printf("Authenticated and decrypted\n");
806
807 /* Clean up */
808 free(output_data);
809
810 /* Destroy the key */
811 psa_destroy_key(handle);
812
mohammad160387a7eeb2018-11-01 11:25:49 +0200813 mbedtls_psa_crypto_free();
814```
815
816### Generating and exporting keys
817
818Mbed Crypto provides a simple way to generate a key or key pair.
819
Guy Wildc03c0fc2019-09-03 13:18:04 +0300820**Prerequisites to using key generation and export APIs:**
821* Initialize the library with a successful call to `psa_crypto_init()`.
mohammad160387a7eeb2018-11-01 11:25:49 +0200822
Guy Wildc03c0fc2019-09-03 13:18:04 +0300823**To generate an ECDSA key:**
Jaeden Amero884738a2019-08-16 17:58:31 +01008241. Set the desired key attributes for key generation by calling
825 `psa_set_key_algorithm()` with the chosen ECDSA algorithm (such as
Guy Wildc03c0fc2019-09-03 13:18:04 +0300826 `PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256)`). Do not set
827 `PSA_KEY_USAGE_EXPORT` because we only want to export the public key, not the key
Jaeden Amero884738a2019-08-16 17:58:31 +0100828 pair (or private key).
8291. Generate a key by calling `psa_generate_key()`.
Guy Wildc03c0fc2019-09-03 13:18:04 +03008301. Export the generated public key by calling `psa_export_public_key()`:
mohammad160387a7eeb2018-11-01 11:25:49 +0200831```C
Jaeden Amero884738a2019-08-16 17:58:31 +0100832 enum {
833 key_bits = 256,
834 };
835 psa_status_t status;
mohammad160387a7eeb2018-11-01 11:25:49 +0200836 size_t exported_length = 0;
Jaeden Amero884738a2019-08-16 17:58:31 +0100837 static uint8_t exported[PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits)];
838 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
839 psa_key_handle_t handle;
mohammad160387a7eeb2018-11-01 11:25:49 +0200840
Jaeden Amero884738a2019-08-16 17:58:31 +0100841 printf("Generate a key pair...\t");
842 fflush(stdout);
mohammad160387a7eeb2018-11-01 11:25:49 +0200843
Jaeden Amero884738a2019-08-16 17:58:31 +0100844 /* Initialize PSA Crypto */
845 status = psa_crypto_init();
846 if (status != PSA_SUCCESS) {
847 printf("Failed to initialize PSA Crypto\n");
848 return;
849 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200850
851 /* Generate a key */
Jaeden Amero884738a2019-08-16 17:58:31 +0100852 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN);
853 psa_set_key_algorithm(&attributes,
854 PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256));
855 psa_set_key_type(&attributes,
856 PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1));
857 psa_set_key_bits(&attributes, key_bits);
858 status = psa_generate_key(&attributes, &handle);
859 if (status != PSA_SUCCESS) {
860 printf("Failed to generate key\n");
861 return;
862 }
863 psa_reset_key_attributes(&attributes);
mohammad160387a7eeb2018-11-01 11:25:49 +0200864
Jaeden Amero884738a2019-08-16 17:58:31 +0100865 status = psa_export_public_key(handle, exported, sizeof(exported),
866 &exported_length);
867 if (status != PSA_SUCCESS) {
868 printf("Failed to export public key %ld\n", status);
869 return;
870 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200871
Jaeden Amero884738a2019-08-16 17:58:31 +0100872 printf("Exported a public key\n");
873
874 /* Destroy the key */
875 psa_destroy_key(handle);
876
mohammad160387a7eeb2018-11-01 11:25:49 +0200877 mbedtls_psa_crypto_free();
878```
879
Guy Wildc03c0fc2019-09-03 13:18:04 +0300880### More about the Mbed Crypto
mohammad160387a7eeb2018-11-01 11:25:49 +0200881
Guy Wildc03c0fc2019-09-03 13:18:04 +0300882For more information about PSA Crypto, download the *PSA Cryptography API* PDF under [PSA APIs](https://developer.arm.com/architectures/security-architectures/platform-security-architecture#implement).