blob: 15410c1186396e07535d3c8427628e47e99cd6b1 [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 Wild5033fdd2019-09-04 09:14:55 +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 Wild5033fdd2019-09-04 09:14:55 +030067import it. Importing the key creates 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 Wild802b19f2019-09-03 16:40:44 +030070**Prerequisites to importing keys:**
Guy Wildc03c0fc2019-09-03 13:18:04 +030071* 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 Wild5033fdd2019-09-04 09:14:55 +0300124This example shows how to sign a hash that has already been calculated:
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;
Guy Wild5033fdd2019-09-04 09:14:55 +0300129 uint8_t hash[32] = {0x50, 0xd8, 0x58, 0xe0, 0x98, 0x5e, 0xcc, 0x7f,
130 0x60, 0x41, 0x8a, 0xaf, 0x0c, 0xc5, 0xab, 0x58,
131 0x7f, 0x42, 0xc2, 0x57, 0x0a, 0x88, 0x40, 0x95,
132 0xa9, 0xe8, 0xcc, 0xac, 0xd0, 0xf6, 0x54, 0x5c};
Jaeden Amero884738a2019-08-16 17:58:31 +0100133 uint8_t signature[PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE] = {0};
mohammad160387a7eeb2018-11-01 11:25:49 +0200134 size_t signature_length;
Jaeden Amero884738a2019-08-16 17:58:31 +0100135 psa_key_handle_t handle;
mohammad160387a7eeb2018-11-01 11:25:49 +0200136
Jaeden Amero884738a2019-08-16 17:58:31 +0100137 printf("Sign a message...\t");
138 fflush(stdout);
139
140 /* Initialize PSA Crypto */
mohammad160387a7eeb2018-11-01 11:25:49 +0200141 status = psa_crypto_init();
Jaeden Amero884738a2019-08-16 17:58:31 +0100142 if (status != PSA_SUCCESS) {
143 printf("Failed to initialize PSA Crypto\n");
144 return;
145 }
146
147 /* Set key attributes */
148 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN);
149 psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_SIGN_RAW);
150 psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR);
151 psa_set_key_bits(&attributes, 1024);
mohammad160387a7eeb2018-11-01 11:25:49 +0200152
153 /* Import the key */
Jaeden Amero884738a2019-08-16 17:58:31 +0100154 status = psa_import_key(&attributes, key, sizeof(key), &handle);
155 if (status != PSA_SUCCESS) {
156 printf("Failed to import key\n");
157 return;
158 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200159
Jaeden Amero884738a2019-08-16 17:58:31 +0100160 /* Sign message using the key */
161 status = psa_asymmetric_sign(handle, PSA_ALG_RSA_PKCS1V15_SIGN_RAW,
162 hash, sizeof(hash),
mohammad160387a7eeb2018-11-01 11:25:49 +0200163 signature, sizeof(signature),
164 &signature_length);
Jaeden Amero884738a2019-08-16 17:58:31 +0100165 if (status != PSA_SUCCESS) {
166 printf("Failed to sign\n");
167 return;
168 }
169
170 printf("Signed a message\n");
171
172 /* Free the attributes */
173 psa_reset_key_attributes(&attributes);
174
mohammad160387a7eeb2018-11-01 11:25:49 +0200175 /* Destroy the key */
Jaeden Amero884738a2019-08-16 17:58:31 +0100176 psa_destroy_key(handle);
177
mohammad160387a7eeb2018-11-01 11:25:49 +0200178 mbedtls_psa_crypto_free();
179```
180
Jaeden Amero884738a2019-08-16 17:58:31 +0100181### Using symmetric ciphers
mohammad160387a7eeb2018-11-01 11:25:49 +0200182
Guy Wildc03c0fc2019-09-03 13:18:04 +0300183Mbed Crypto supports encrypting and decrypting messages using various symmetric cipher algorithms (both block and stream ciphers).
mohammad160387a7eeb2018-11-01 11:25:49 +0200184
Guy Wildc03c0fc2019-09-03 13:18:04 +0300185**Prerequisites to working with the symmetric cipher API:**
186* Initialize the library with a successful call to `psa_crypto_init()`.
Guy Wild5033fdd2019-09-04 09:14:55 +0300187* Have a handle to a symmetric key. This key's usage flags must include `PSA_KEY_USAGE_ENCRYPT` to allow encryption or `PSA_KEY_USAGE_DECRYPT` to allow decryption.
mohammad160387a7eeb2018-11-01 11:25:49 +0200188
Guy Wildc03c0fc2019-09-03 13:18:04 +0300189**To encrypt a message with a symmetric cipher:**
mohammad160387a7eeb2018-11-01 11:25:49 +02001901. Allocate an operation (`psa_cipher_operation_t`) structure to pass to the cipher functions.
Guy Wild33d421d2019-09-04 09:16:14 +03001911. Initialize the operation structure to zero or to `PSA_CIPHER_OPERATION_INIT`.
1921. Call `psa_cipher_encrypt_setup()` to specify the algorithm and the key to be used.
Guy Wildc03c0fc2019-09-03 13:18:04 +03001931. 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.
Guy Wild802b19f2019-09-03 16:40:44 +03001941. Call `psa_cipher_update()` one or more times, passing the whole message or a fragment of the message on each call.
Guy Wildc03c0fc2019-09-03 13:18:04 +03001951. Call `psa_cipher_finish()` to end the operation and output the encrypted message.
mohammad160387a7eeb2018-11-01 11:25:49 +0200196
Guy Wild802b19f2019-09-03 16:40:44 +0300197This example shows how to encrypt data using an Advanced Encryption Standard (AES) key in Cipher Block Chaining (CBC) mode with no padding (assuming all prerequisites have been fulfilled):
mohammad160387a7eeb2018-11-01 11:25:49 +0200198```c
Jaeden Amero884738a2019-08-16 17:58:31 +0100199 enum {
200 block_size = PSA_BLOCK_CIPHER_BLOCK_SIZE(PSA_KEY_TYPE_AES),
201 };
202 psa_status_t status;
203 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
mohammad160387a7eeb2018-11-01 11:25:49 +0200204 psa_algorithm_t alg = PSA_ALG_CBC_NO_PADDING;
Jaeden Amero884738a2019-08-16 17:58:31 +0100205 uint8_t plaintext[block_size] = SOME_PLAINTEXT;
206 uint8_t iv[block_size];
mohammad160387a7eeb2018-11-01 11:25:49 +0200207 size_t iv_len;
Jaeden Amero884738a2019-08-16 17:58:31 +0100208 uint8_t key[] = AES_KEY;
209 uint8_t output[block_size];
mohammad160387a7eeb2018-11-01 11:25:49 +0200210 size_t output_len;
Jaeden Amero884738a2019-08-16 17:58:31 +0100211 psa_key_handle_t handle;
212 psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
mohammad160387a7eeb2018-11-01 11:25:49 +0200213
Jaeden Amero884738a2019-08-16 17:58:31 +0100214 printf("Encrypt with cipher...\t");
215 fflush(stdout);
mohammad160387a7eeb2018-11-01 11:25:49 +0200216
Jaeden Amero884738a2019-08-16 17:58:31 +0100217 /* Initialize PSA Crypto */
218 status = psa_crypto_init();
219 if (status != PSA_SUCCESS)
220 {
221 printf("Failed to initialize PSA Crypto\n");
222 return;
223 }
224
225 /* Import a key */
226 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
227 psa_set_key_algorithm(&attributes, alg);
228 psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
229 psa_set_key_bits(&attributes, 128);
230 status = psa_import_key(&attributes, key, sizeof(key), &handle);
231 if (status != PSA_SUCCESS) {
232 printf("Failed to import a key\n");
233 return;
234 }
235 psa_reset_key_attributes(&attributes);
236
237 /* Encrypt the plaintext */
238 status = psa_cipher_encrypt_setup(&operation, handle, alg);
239 if (status != PSA_SUCCESS) {
240 printf("Failed to begin cipher operation\n");
241 return;
242 }
243 status = psa_cipher_generate_iv(&operation, iv, sizeof(iv), &iv_len);
244 if (status != PSA_SUCCESS) {
245 printf("Failed to generate IV\n");
246 return;
247 }
248 status = psa_cipher_update(&operation, plaintext, sizeof(plaintext),
249 output, sizeof(output), &output_len);
250 if (status != PSA_SUCCESS) {
251 printf("Failed to update cipher operation\n");
252 return;
253 }
254 status = psa_cipher_finish(&operation, output + output_len,
255 sizeof(output) - output_len, &output_len);
256 if (status != PSA_SUCCESS) {
257 printf("Failed to finish cipher operation\n");
258 return;
259 }
260 printf("Encrypted plaintext\n");
261
mohammad160387a7eeb2018-11-01 11:25:49 +0200262 /* Clean up cipher operation context */
263 psa_cipher_abort(&operation);
Jaeden Amero884738a2019-08-16 17:58:31 +0100264
265 /* Destroy the key */
266 psa_destroy_key(handle);
267
268 mbedtls_psa_crypto_free();
mohammad160387a7eeb2018-11-01 11:25:49 +0200269```
270
Guy Wildc03c0fc2019-09-03 13:18:04 +0300271**To decrypt a message with a symmetric cipher:**
mohammad160387a7eeb2018-11-01 11:25:49 +02002721. Allocate an operation (`psa_cipher_operation_t`) structure to pass to the cipher functions.
Guy Wildc03c0fc2019-09-03 13:18:04 +03002731. Call `psa_cipher_decrypt_setup()` to initialize the operation structure and to specify the algorithm and the key to be used.
2741. Call `psa_cipher_set_iv()` with the IV for the decryption.
Guy Wild802b19f2019-09-03 16:40:44 +03002751. Call `psa_cipher_update()` one or more times, passing the whole message or a fragment of the message on each call.
Guy Wildc03c0fc2019-09-03 13:18:04 +03002761. Call `psa_cipher_finish()` to end the operation and output the decrypted message.
mohammad160387a7eeb2018-11-01 11:25:49 +0200277
Guy Wildc03c0fc2019-09-03 13:18:04 +0300278This example shows how to decrypt encrypted data using an AES key in CBC mode with no padding
mohammad160387a7eeb2018-11-01 11:25:49 +0200279(assuming all prerequisites have been fulfilled):
280```c
Jaeden Amero884738a2019-08-16 17:58:31 +0100281 enum {
282 block_size = PSA_BLOCK_CIPHER_BLOCK_SIZE(PSA_KEY_TYPE_AES),
283 };
284 psa_status_t status;
285 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
mohammad160387a7eeb2018-11-01 11:25:49 +0200286 psa_algorithm_t alg = PSA_ALG_CBC_NO_PADDING;
Jaeden Amero884738a2019-08-16 17:58:31 +0100287 psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
288 uint8_t ciphertext[block_size] = SOME_CIPHERTEXT;
289 uint8_t iv[block_size] = ENCRYPTED_WITH_IV;
290 uint8_t key[] = AES_KEY;
291 uint8_t output[block_size];
mohammad160387a7eeb2018-11-01 11:25:49 +0200292 size_t output_len;
Jaeden Amero884738a2019-08-16 17:58:31 +0100293 psa_key_handle_t handle;
mohammad160387a7eeb2018-11-01 11:25:49 +0200294
Jaeden Amero884738a2019-08-16 17:58:31 +0100295 printf("Decrypt with cipher...\t");
296 fflush(stdout);
mohammad160387a7eeb2018-11-01 11:25:49 +0200297
Jaeden Amero884738a2019-08-16 17:58:31 +0100298 /* Initialize PSA Crypto */
299 status = psa_crypto_init();
300 if (status != PSA_SUCCESS)
301 {
302 printf("Failed to initialize PSA Crypto\n");
303 return;
304 }
305
306 /* Import a key */
307 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT);
308 psa_set_key_algorithm(&attributes, alg);
309 psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
310 psa_set_key_bits(&attributes, 128);
311 status = psa_import_key(&attributes, key, sizeof(key), &handle);
312 if (status != PSA_SUCCESS) {
313 printf("Failed to import a key\n");
314 return;
315 }
316 psa_reset_key_attributes(&attributes);
317
318 /* Decrypt the ciphertext */
319 status = psa_cipher_decrypt_setup(&operation, handle, alg);
320 if (status != PSA_SUCCESS) {
321 printf("Failed to begin cipher operation\n");
322 return;
323 }
324 status = psa_cipher_set_iv(&operation, iv, sizeof(iv));
325 if (status != PSA_SUCCESS) {
326 printf("Failed to set IV\n");
327 return;
328 }
329 status = psa_cipher_update(&operation, ciphertext, sizeof(ciphertext),
330 output, sizeof(output), &output_len);
331 if (status != PSA_SUCCESS) {
332 printf("Failed to update cipher operation\n");
333 return;
334 }
335 status = psa_cipher_finish(&operation, output + output_len,
336 sizeof(output) - output_len, &output_len);
337 if (status != PSA_SUCCESS) {
338 printf("Failed to finish cipher operation\n");
339 return;
340 }
341 printf("Decrypted ciphertext\n");
342
mohammad160387a7eeb2018-11-01 11:25:49 +0200343 /* Clean up cipher operation context */
344 psa_cipher_abort(&operation);
Jaeden Amero884738a2019-08-16 17:58:31 +0100345
346 /* Destroy the key */
347 psa_destroy_key(handle);
348
349 mbedtls_psa_crypto_free();
mohammad160387a7eeb2018-11-01 11:25:49 +0200350```
351
352#### Handling cipher operation contexts
353
Guy Wildc03c0fc2019-09-03 13:18:04 +0300354After 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 +0200355
Guy Wildc03c0fc2019-09-03 13:18:04 +0300356The call to `psa_cipher_abort()` frees any resources associated with the operation, except for the operation structure itself.
mohammad160387a7eeb2018-11-01 11:25:49 +0200357
Guy Wildc03c0fc2019-09-03 13:18:04 +0300358Mbed Crypto implicitly calls `psa_cipher_abort()` when:
359* A call to `psa_cipher_generate_iv()`, `psa_cipher_set_iv()` or `psa_cipher_update()` fails (returning any status other than `PSA_SUCCESS`).
360* A call to `psa_cipher_finish()` succeeds or fails.
mohammad160387a7eeb2018-11-01 11:25:49 +0200361
Guy Wildc03c0fc2019-09-03 13:18:04 +0300362After 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 +0200363
Guy Wildc03c0fc2019-09-03 13:18:04 +0300364You 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()`).
365
366Making 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 +0200367
368### Hashing a message
369
Jaeden Amero884738a2019-08-16 17:58:31 +0100370Mbed Crypto lets you compute and verify hashes using various hashing
371algorithms.
mohammad160387a7eeb2018-11-01 11:25:49 +0200372
Guy Wildc03c0fc2019-09-03 13:18:04 +0300373**Prerequisites to working with the hash APIs:**
374* Initialize the library with a successful call to `psa_crypto_init()`.
mohammad160387a7eeb2018-11-01 11:25:49 +0200375
Guy Wildc03c0fc2019-09-03 13:18:04 +0300376**To calculate a hash:**
mohammad160387a7eeb2018-11-01 11:25:49 +02003771. Allocate an operation structure (`psa_hash_operation_t`) to pass to the hash functions.
Guy Wildc03c0fc2019-09-03 13:18:04 +03003781. Call `psa_hash_setup()` to initialize the operation structure and specify the hash algorithm.
Guy Wild802b19f2019-09-03 16:40:44 +03003791. Call `psa_hash_update()` one or more times, passing the whole message or a fragment of the message on each call.
Guy Wildc03c0fc2019-09-03 13:18:04 +03003801. 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 +0200381
Guy Wildc03c0fc2019-09-03 13:18:04 +0300382This example shows how to calculate the `SHA-256` hash of a message:
mohammad160387a7eeb2018-11-01 11:25:49 +0200383```c
Jaeden Amero884738a2019-08-16 17:58:31 +0100384 psa_status_t status;
mohammad160387a7eeb2018-11-01 11:25:49 +0200385 psa_algorithm_t alg = PSA_ALG_SHA_256;
Jaeden Amero884738a2019-08-16 17:58:31 +0100386 psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
mohammad160387a7eeb2018-11-01 11:25:49 +0200387 unsigned char input[] = { 'a', 'b', 'c' };
388 unsigned char actual_hash[PSA_HASH_MAX_SIZE];
389 size_t actual_hash_len;
390
Jaeden Amero884738a2019-08-16 17:58:31 +0100391 printf("Hash a message...\t");
392 fflush(stdout);
393
394 /* Initialize PSA Crypto */
395 status = psa_crypto_init();
396 if (status != PSA_SUCCESS) {
397 printf("Failed to initialize PSA Crypto\n");
398 return;
399 }
400
mohammad160387a7eeb2018-11-01 11:25:49 +0200401 /* Compute hash of message */
Jaeden Amero884738a2019-08-16 17:58:31 +0100402 status = psa_hash_setup(&operation, alg);
403 if (status != PSA_SUCCESS) {
404 printf("Failed to begin hash operation\n");
405 return;
406 }
407 status = psa_hash_update(&operation, input, sizeof(input));
408 if (status != PSA_SUCCESS) {
409 printf("Failed to update hash operation\n");
410 return;
411 }
412 status = psa_hash_finish(&operation, actual_hash, sizeof(actual_hash),
413 &actual_hash_len);
414 if (status != PSA_SUCCESS) {
415 printf("Failed to finish hash operation\n");
416 return;
417 }
418
419 printf("Hashed a message\n");
mohammad160387a7eeb2018-11-01 11:25:49 +0200420
421 /* Clean up hash operation context */
422 psa_hash_abort(&operation);
Jaeden Amero884738a2019-08-16 17:58:31 +0100423
424 mbedtls_psa_crypto_free();
mohammad160387a7eeb2018-11-01 11:25:49 +0200425```
426
Guy Wildc03c0fc2019-09-03 13:18:04 +0300427This example shows how to verify the `SHA-256` hash of a message:
mohammad160387a7eeb2018-11-01 11:25:49 +0200428```c
Jaeden Amero884738a2019-08-16 17:58:31 +0100429 psa_status_t status;
mohammad160387a7eeb2018-11-01 11:25:49 +0200430 psa_algorithm_t alg = PSA_ALG_SHA_256;
Jaeden Amero884738a2019-08-16 17:58:31 +0100431 psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
mohammad160387a7eeb2018-11-01 11:25:49 +0200432 unsigned char input[] = { 'a', 'b', 'c' };
433 unsigned char expected_hash[] = {
434 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, 0xde,
435 0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
436 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad
437 };
438 size_t expected_hash_len = PSA_HASH_SIZE(alg);
439
Jaeden Amero884738a2019-08-16 17:58:31 +0100440 printf("Verify a hash...\t");
441 fflush(stdout);
442
443 /* Initialize PSA Crypto */
444 status = psa_crypto_init();
445 if (status != PSA_SUCCESS) {
446 printf("Failed to initialize PSA Crypto\n");
447 return;
448 }
449
mohammad160387a7eeb2018-11-01 11:25:49 +0200450 /* Verify message hash */
Jaeden Amero884738a2019-08-16 17:58:31 +0100451 status = psa_hash_setup(&operation, alg);
452 if (status != PSA_SUCCESS) {
453 printf("Failed to begin hash operation\n");
454 return;
455 }
456 status = psa_hash_update(&operation, input, sizeof(input));
457 if (status != PSA_SUCCESS) {
458 printf("Failed to update hash operation\n");
459 return;
460 }
461 status = psa_hash_verify(&operation, expected_hash, expected_hash_len);
462 if (status != PSA_SUCCESS) {
463 printf("Failed to verify hash\n");
464 return;
465 }
466
467 printf("Verified a hash\n");
468
469 /* Clean up hash operation context */
470 psa_hash_abort(&operation);
471
472 mbedtls_psa_crypto_free();
mohammad160387a7eeb2018-11-01 11:25:49 +0200473```
474
475The API provides the macro `PSA_HASH_SIZE`, which returns the expected hash length (in bytes) for the specified algorithm.
476
477#### Handling hash operation contexts
478
Guy Wildc03c0fc2019-09-03 13:18:04 +0300479After 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 +0200480
Guy Wildc03c0fc2019-09-03 13:18:04 +0300481Mbed Crypto implicitly calls `psa_hash_abort()` when:
4821. A call to `psa_hash_update()` fails (returning any status other than `PSA_SUCCESS`).
4831. A call to `psa_hash_finish()` succeeds or fails.
4841. A call to `psa_hash_verify()` succeeds or fails.
mohammad160387a7eeb2018-11-01 11:25:49 +0200485
Guy Wildc03c0fc2019-09-03 13:18:04 +0300486After 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 +0200487
Guy Wildc03c0fc2019-09-03 13:18:04 +0300488You 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 +0200489
Guy Wildc03c0fc2019-09-03 13:18:04 +0300490Making 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 +0200491
492### Generating a random value
493
Guy Wildc03c0fc2019-09-03 13:18:04 +0300494Mbed Crypto can generate random data.
mohammad160387a7eeb2018-11-01 11:25:49 +0200495
Guy Wild802b19f2019-09-03 16:40:44 +0300496**Prerequisites to generating random data:**
Jaeden Amero884738a2019-08-16 17:58:31 +0100497* Initialize the library with a successful call to `psa_crypto_init()`.
mohammad160387a7eeb2018-11-01 11:25:49 +0200498
Guy Wild802b19f2019-09-03 16:40:44 +0300499<span class="notes">**Note:** To generate a random key, use `psa_generate_key()` instead of `psa_generate_random()`.</span>
500
501This example shows how to generate ten bytes of random data by calling `psa_generate_random()`:
mohammad160387a7eeb2018-11-01 11:25:49 +0200502```C
503 psa_status_t status;
504 uint8_t random[10] = { 0 };
mohammad160387a7eeb2018-11-01 11:25:49 +0200505
Jaeden Amero884738a2019-08-16 17:58:31 +0100506 printf("Generate random...\t");
507 fflush(stdout);
508
509 /* Initialize PSA Crypto */
510 status = psa_crypto_init();
511 if (status != PSA_SUCCESS) {
512 printf("Failed to initialize PSA Crypto\n");
513 return;
514 }
515
516 status = psa_generate_random(random, sizeof(random));
517 if (status != PSA_SUCCESS) {
518 printf("Failed to generate a random value\n");
519 return;
520 }
521
522 printf("Generated random data\n");
523
524 /* Clean up */
mohammad160387a7eeb2018-11-01 11:25:49 +0200525 mbedtls_psa_crypto_free();
526```
527
528### Deriving a new key from an existing key
529
Jaeden Amero884738a2019-08-16 17:58:31 +0100530Mbed Crypto provides a key derivation API that lets you derive new keys from
531existing ones. The key derivation API has functions to take inputs, including
532other keys and data, and functions to generate outputs, such as new keys or
Guy Wildc03c0fc2019-09-03 13:18:04 +0300533other data.
mohammad160387a7eeb2018-11-01 11:25:49 +0200534
Guy Wildc03c0fc2019-09-03 13:18:04 +0300535You must first initialize and set up a key derivation context,
536provided 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.
537
538See the documentation for the particular algorithm (such as HKDF or the TLS1.2 PRF) for
539information about which inputs to pass when, and when you can obtain which outputs.
540
541**Prerequisites to working with the key derivation APIs:**
542* Initialize the library with a successful call to `psa_crypto_init()`.
Jaeden Amero884738a2019-08-16 17:58:31 +0100543* Use a key with the appropriate attributes set:
544 * Usage flags set for key derivation (`PSA_KEY_USAGE_DERIVE`)
545 * Key type set to `PSA_KEY_TYPE_DERIVE`.
546 * Algorithm set to a key derivation algorithm
547 (`PSA_ALG_HKDF(PSA_ALG_SHA_256)`).
mohammad160387a7eeb2018-11-01 11:25:49 +0200548
Guy Wildc03c0fc2019-09-03 13:18:04 +0300549**To derive a new AES-CTR 128-bit encryption key into a given key slot using HKDF
550with a given key, salt and information:**
551
5521. Set up the key derivation context using the `psa_key_derivation_setup()`
Jaeden Amero884738a2019-08-16 17:58:31 +0100553function, specifying the derivation algorithm `PSA_ALG_HKDF(PSA_ALG_SHA_256)`.
Guy Wildc03c0fc2019-09-03 13:18:04 +03005541. Provide an optional salt with `psa_key_derivation_input_bytes()`.
Guy Wild802b19f2019-09-03 16:40:44 +03005551. Provide `info` with `psa_key_derivation_input_bytes()`.
5561. Provide `secret` with `psa_key_derivation_input_key()`, referencing a key that
Jaeden Amero884738a2019-08-16 17:58:31 +0100557 can be used for key derivation.
5581. Set the key attributes desired for the new derived key. We'll set
Guy Wildc03c0fc2019-09-03 13:18:04 +0300559 the `PSA_KEY_USAGE_ENCRYPT` parameter and the `PSA_ALG_CTR` algorithm for this
Jaeden Amero884738a2019-08-16 17:58:31 +0100560 example.
5611. Derive the key by calling `psa_key_derivation_output_key()`.
5621. Clean up the key derivation context.
mohammad160387a7eeb2018-11-01 11:25:49 +0200563
Guy Wildc03c0fc2019-09-03 13:18:04 +0300564At this point, the derived key slot holds a new 128-bit AES-CTR encryption key
565derived from the key, salt and information provided:
mohammad160387a7eeb2018-11-01 11:25:49 +0200566```C
Jaeden Amero884738a2019-08-16 17:58:31 +0100567 psa_status_t status;
568 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
569 static const unsigned char key[] = {
mohammad160387a7eeb2018-11-01 11:25:49 +0200570 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
571 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
572 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
573 0x0b };
Jaeden Amero884738a2019-08-16 17:58:31 +0100574 static const unsigned char salt[] = {
575 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
576 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c };
577 static const unsigned char info[] = {
578 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6,
579 0xf7, 0xf8, 0xf9 };
mohammad160387a7eeb2018-11-01 11:25:49 +0200580 psa_algorithm_t alg = PSA_ALG_HKDF(PSA_ALG_SHA_256);
Jaeden Amero884738a2019-08-16 17:58:31 +0100581 psa_key_derivation_operation_t operation =
582 PSA_KEY_DERIVATION_OPERATION_INIT;
mohammad160387a7eeb2018-11-01 11:25:49 +0200583 size_t derived_bits = 128;
584 size_t capacity = PSA_BITS_TO_BYTES(derived_bits);
Jaeden Amero884738a2019-08-16 17:58:31 +0100585 psa_key_handle_t base_key;
586 psa_key_handle_t derived_key;
mohammad160387a7eeb2018-11-01 11:25:49 +0200587
Jaeden Amero884738a2019-08-16 17:58:31 +0100588 printf("Derive a key (HKDF)...\t");
589 fflush(stdout);
590
591 /* Initialize PSA Crypto */
mohammad160387a7eeb2018-11-01 11:25:49 +0200592 status = psa_crypto_init();
Jaeden Amero884738a2019-08-16 17:58:31 +0100593 if (status != PSA_SUCCESS) {
594 printf("Failed to initialize PSA Crypto\n");
595 return;
596 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200597
Jaeden Amero884738a2019-08-16 17:58:31 +0100598 /* Import a key for use in key derivation. If such a key has already been
599 * generated or imported, you can skip this part. */
600 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE);
601 psa_set_key_algorithm(&attributes, alg);
602 psa_set_key_type(&attributes, PSA_KEY_TYPE_DERIVE);
603 status = psa_import_key(&attributes, key, sizeof(key), &base_key);
604 if (status != PSA_SUCCESS) {
605 printf("Failed to import a key\n");
606 return;
607 }
608 psa_reset_key_attributes(&attributes);
mohammad160387a7eeb2018-11-01 11:25:49 +0200609
Jaeden Amero884738a2019-08-16 17:58:31 +0100610 /* Derive a key */
611 status = psa_key_derivation_setup(&operation, alg);
612 if (status != PSA_SUCCESS) {
613 printf("Failed to begin key derivation\n");
614 return;
615 }
616 status = psa_key_derivation_set_capacity(&operation, capacity);
617 if (status != PSA_SUCCESS) {
618 printf("Failed to set capacity\n");
619 return;
620 }
621 status = psa_key_derivation_input_bytes(&operation,
622 PSA_KEY_DERIVATION_INPUT_SALT,
623 salt, sizeof(salt));
624 if (status != PSA_SUCCESS) {
625 printf("Failed to input salt (extract)\n");
626 return;
627 }
628 status = psa_key_derivation_input_key(&operation,
629 PSA_KEY_DERIVATION_INPUT_SECRET,
630 base_key);
631 if (status != PSA_SUCCESS) {
632 printf("Failed to input key (extract)\n");
633 return;
634 }
635 status = psa_key_derivation_input_bytes(&operation,
636 PSA_KEY_DERIVATION_INPUT_INFO,
637 info, sizeof(info));
638 if (status != PSA_SUCCESS) {
639 printf("Failed to input info (expand)\n");
640 return;
641 }
642 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
643 psa_set_key_algorithm(&attributes, PSA_ALG_CTR);
644 psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
645 psa_set_key_bits(&attributes, 128);
646 status = psa_key_derivation_output_key(&attributes, &operation,
647 &derived_key);
648 if (status != PSA_SUCCESS) {
649 printf("Failed to derive key\n");
650 return;
651 }
652 psa_reset_key_attributes(&attributes);
mohammad160387a7eeb2018-11-01 11:25:49 +0200653
Jaeden Amero884738a2019-08-16 17:58:31 +0100654 printf("Derived key\n");
mohammad160387a7eeb2018-11-01 11:25:49 +0200655
Jaeden Amero884738a2019-08-16 17:58:31 +0100656 /* Clean up key derivation operation */
657 psa_key_derivation_abort(&operation);
mohammad160387a7eeb2018-11-01 11:25:49 +0200658
Jaeden Amero884738a2019-08-16 17:58:31 +0100659 /* Destroy the keys */
660 psa_destroy_key(derived_key);
661 psa_destroy_key(base_key);
mohammad160387a7eeb2018-11-01 11:25:49 +0200662
mohammad160387a7eeb2018-11-01 11:25:49 +0200663 mbedtls_psa_crypto_free();
664```
665
666### Authenticating and encrypting or decrypting a message
667
Guy Wildc03c0fc2019-09-03 13:18:04 +0300668Mbed 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 +0200669
Guy Wildc03c0fc2019-09-03 13:18:04 +0300670**Prerequisites to working with the AEAD cipher APIs:**
671* Initialize the library with a successful call to `psa_crypto_init()`.
672* 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 +0200673
Guy Wildc03c0fc2019-09-03 13:18:04 +0300674This example shows how to authenticate and encrypt a message:
mohammad160387a7eeb2018-11-01 11:25:49 +0200675```C
mohammad160387a7eeb2018-11-01 11:25:49 +0200676 psa_status_t status;
Jaeden Amero884738a2019-08-16 17:58:31 +0100677 static const uint8_t key[] = {
678 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
679 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF };
680 static const uint8_t nonce[] = {
681 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
682 0x08, 0x09, 0x0A, 0x0B };
683 static const uint8_t additional_data[] = {
684 0xEC, 0x46, 0xBB, 0x63, 0xB0, 0x25,
685 0x20, 0xC3, 0x3C, 0x49, 0xFD, 0x70 };
686 static const uint8_t input_data[] = {
687 0xB9, 0x6B, 0x49, 0xE2, 0x1D, 0x62, 0x17, 0x41,
688 0x63, 0x28, 0x75, 0xDB, 0x7F, 0x6C, 0x92, 0x43,
689 0xD2, 0xD7, 0xC2 };
690 uint8_t *output_data = NULL;
mohammad160387a7eeb2018-11-01 11:25:49 +0200691 size_t output_size = 0;
692 size_t output_length = 0;
693 size_t tag_length = 16;
Jaeden Amero884738a2019-08-16 17:58:31 +0100694 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
695 psa_key_handle_t handle;
696
697 printf("Authenticate encrypt...\t");
698 fflush(stdout);
699
700 /* Initialize PSA Crypto */
701 status = psa_crypto_init();
702 if (status != PSA_SUCCESS) {
703 printf("Failed to initialize PSA Crypto\n");
704 return;
705 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200706
707 output_size = sizeof(input_data) + tag_length;
Jaeden Amero884738a2019-08-16 17:58:31 +0100708 output_data = (uint8_t *)malloc(output_size);
709 if (!output_data) {
710 printf("Out of memory\n");
711 return;
712 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200713
Jaeden Amero884738a2019-08-16 17:58:31 +0100714 /* Import a key */
715 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
716 psa_set_key_algorithm(&attributes, PSA_ALG_CCM);
717 psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
718 psa_set_key_bits(&attributes, 128);
719 status = psa_import_key(&attributes, key, sizeof(key), &handle);
720 psa_reset_key_attributes(&attributes);
mohammad160387a7eeb2018-11-01 11:25:49 +0200721
Jaeden Amero884738a2019-08-16 17:58:31 +0100722 /* Authenticate and encrypt */
723 status = psa_aead_encrypt(handle, PSA_ALG_CCM,
mohammad160387a7eeb2018-11-01 11:25:49 +0200724 nonce, sizeof(nonce),
725 additional_data, sizeof(additional_data),
726 input_data, sizeof(input_data),
727 output_data, output_size,
728 &output_length);
Jaeden Amero884738a2019-08-16 17:58:31 +0100729 if (status != PSA_SUCCESS) {
730 printf("Failed to authenticate and encrypt\n");
731 return;
732 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200733
Jaeden Amero884738a2019-08-16 17:58:31 +0100734 printf("Authenticated and encrypted\n");
735
736 /* Clean up */
737 free(output_data);
738
739 /* Destroy the key */
740 psa_destroy_key(handle);
741
mohammad160387a7eeb2018-11-01 11:25:49 +0200742 mbedtls_psa_crypto_free();
743```
744
Guy Wildc03c0fc2019-09-03 13:18:04 +0300745This example shows how to authenticate and decrypt a message:
mohammad160387a7eeb2018-11-01 11:25:49 +0200746
747```C
mohammad160387a7eeb2018-11-01 11:25:49 +0200748 psa_status_t status;
Jaeden Amero884738a2019-08-16 17:58:31 +0100749 static const uint8_t key[] = {
mohammad160387a7eeb2018-11-01 11:25:49 +0200750 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
Jaeden Amero884738a2019-08-16 17:58:31 +0100751 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF };
752 static const uint8_t nonce[] = {
753 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
754 0x08, 0x09, 0x0A, 0x0B };
755 static const uint8_t additional_data[] = {
756 0xEC, 0x46, 0xBB, 0x63, 0xB0, 0x25,
757 0x20, 0xC3, 0x3C, 0x49, 0xFD, 0x70 };
758 static const uint8_t input_data[] = {
759 0x20, 0x30, 0xE0, 0x36, 0xED, 0x09, 0xA0, 0x45, 0xAF, 0x3C, 0xBA, 0xEE,
760 0x0F, 0xC8, 0x48, 0xAF, 0xCD, 0x89, 0x54, 0xF4, 0xF6, 0x3F, 0x28, 0x9A,
761 0xA1, 0xDD, 0xB2, 0xB8, 0x09, 0xCD, 0x7C, 0xE1, 0x46, 0xE9, 0x98 };
762 uint8_t *output_data = NULL;
mohammad160387a7eeb2018-11-01 11:25:49 +0200763 size_t output_size = 0;
764 size_t output_length = 0;
Jaeden Amero884738a2019-08-16 17:58:31 +0100765 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
766 psa_key_handle_t handle;
767
768 printf("Authenticate decrypt...\t");
769 fflush(stdout);
770
771 /* Initialize PSA Crypto */
772 status = psa_crypto_init();
773 if (status != PSA_SUCCESS) {
774 printf("Failed to initialize PSA Crypto\n");
775 return;
776 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200777
778 output_size = sizeof(input_data);
Jaeden Amero884738a2019-08-16 17:58:31 +0100779 output_data = (uint8_t *)malloc(output_size);
780 if (!output_data) {
781 printf("Out of memory\n");
782 return;
783 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200784
Jaeden Amero884738a2019-08-16 17:58:31 +0100785 /* Import a key */
786 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT);
787 psa_set_key_algorithm(&attributes, PSA_ALG_CCM);
788 psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
789 psa_set_key_bits(&attributes, 128);
790 status = psa_import_key(&attributes, key, sizeof(key), &handle);
791 if (status != PSA_SUCCESS) {
792 printf("Failed to import a key\n");
793 return;
794 }
795 psa_reset_key_attributes(&attributes);
mohammad160387a7eeb2018-11-01 11:25:49 +0200796
Jaeden Amero884738a2019-08-16 17:58:31 +0100797 /* Authenticate and decrypt */
798 status = psa_aead_decrypt(handle, 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 decrypt %ld\n", status);
806 return;
807 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200808
Jaeden Amero884738a2019-08-16 17:58:31 +0100809 printf("Authenticated and decrypted\n");
810
811 /* Clean up */
812 free(output_data);
813
814 /* Destroy the key */
815 psa_destroy_key(handle);
816
mohammad160387a7eeb2018-11-01 11:25:49 +0200817 mbedtls_psa_crypto_free();
818```
819
820### Generating and exporting keys
821
822Mbed Crypto provides a simple way to generate a key or key pair.
823
Guy Wildc03c0fc2019-09-03 13:18:04 +0300824**Prerequisites to using key generation and export APIs:**
825* Initialize the library with a successful call to `psa_crypto_init()`.
mohammad160387a7eeb2018-11-01 11:25:49 +0200826
Guy Wildc03c0fc2019-09-03 13:18:04 +0300827**To generate an ECDSA key:**
Jaeden Amero884738a2019-08-16 17:58:31 +01008281. Set the desired key attributes for key generation by calling
829 `psa_set_key_algorithm()` with the chosen ECDSA algorithm (such as
Guy Wildc03c0fc2019-09-03 13:18:04 +0300830 `PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256)`). Do not set
Guy Wild802b19f2019-09-03 16:40:44 +0300831 `PSA_KEY_USAGE_EXPORT`; we only want to export the public key, not the key
Jaeden Amero884738a2019-08-16 17:58:31 +0100832 pair (or private key).
8331. Generate a key by calling `psa_generate_key()`.
Guy Wildc03c0fc2019-09-03 13:18:04 +03008341. Export the generated public key by calling `psa_export_public_key()`:
mohammad160387a7eeb2018-11-01 11:25:49 +0200835```C
Jaeden Amero884738a2019-08-16 17:58:31 +0100836 enum {
837 key_bits = 256,
838 };
839 psa_status_t status;
mohammad160387a7eeb2018-11-01 11:25:49 +0200840 size_t exported_length = 0;
Jaeden Amero884738a2019-08-16 17:58:31 +0100841 static uint8_t exported[PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits)];
842 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
843 psa_key_handle_t handle;
mohammad160387a7eeb2018-11-01 11:25:49 +0200844
Jaeden Amero884738a2019-08-16 17:58:31 +0100845 printf("Generate a key pair...\t");
846 fflush(stdout);
mohammad160387a7eeb2018-11-01 11:25:49 +0200847
Jaeden Amero884738a2019-08-16 17:58:31 +0100848 /* Initialize PSA Crypto */
849 status = psa_crypto_init();
850 if (status != PSA_SUCCESS) {
851 printf("Failed to initialize PSA Crypto\n");
852 return;
853 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200854
855 /* Generate a key */
Jaeden Amero884738a2019-08-16 17:58:31 +0100856 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN);
857 psa_set_key_algorithm(&attributes,
858 PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256));
859 psa_set_key_type(&attributes,
860 PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1));
861 psa_set_key_bits(&attributes, key_bits);
862 status = psa_generate_key(&attributes, &handle);
863 if (status != PSA_SUCCESS) {
864 printf("Failed to generate key\n");
865 return;
866 }
867 psa_reset_key_attributes(&attributes);
mohammad160387a7eeb2018-11-01 11:25:49 +0200868
Jaeden Amero884738a2019-08-16 17:58:31 +0100869 status = psa_export_public_key(handle, exported, sizeof(exported),
870 &exported_length);
871 if (status != PSA_SUCCESS) {
872 printf("Failed to export public key %ld\n", status);
873 return;
874 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200875
Jaeden Amero884738a2019-08-16 17:58:31 +0100876 printf("Exported a public key\n");
877
878 /* Destroy the key */
879 psa_destroy_key(handle);
880
mohammad160387a7eeb2018-11-01 11:25:49 +0200881 mbedtls_psa_crypto_free();
882```
883
Guy Wild802b19f2019-09-03 16:40:44 +0300884### More about the Mbed Crypto API
mohammad160387a7eeb2018-11-01 11:25:49 +0200885
Guy Wildc03c0fc2019-09-03 13:18:04 +0300886For 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).