blob: 5d123a602441a972a0f6028171384891995cf28f [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 Wildeefc5172019-09-04 09:16:53 +03003781. Initialize the operation structure to zero or to `PSA_HASH_OPERATION_INIT`.
3791. Call `psa_hash_setup()` to specify the hash algorithm.
Guy Wild802b19f2019-09-03 16:40:44 +03003801. 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 +03003811. 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 +0200382
Guy Wildc03c0fc2019-09-03 13:18:04 +0300383This example shows how to calculate the `SHA-256` hash of a message:
mohammad160387a7eeb2018-11-01 11:25:49 +0200384```c
Jaeden Amero884738a2019-08-16 17:58:31 +0100385 psa_status_t status;
mohammad160387a7eeb2018-11-01 11:25:49 +0200386 psa_algorithm_t alg = PSA_ALG_SHA_256;
Jaeden Amero884738a2019-08-16 17:58:31 +0100387 psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
mohammad160387a7eeb2018-11-01 11:25:49 +0200388 unsigned char input[] = { 'a', 'b', 'c' };
389 unsigned char actual_hash[PSA_HASH_MAX_SIZE];
390 size_t actual_hash_len;
391
Jaeden Amero884738a2019-08-16 17:58:31 +0100392 printf("Hash a message...\t");
393 fflush(stdout);
394
395 /* Initialize PSA Crypto */
396 status = psa_crypto_init();
397 if (status != PSA_SUCCESS) {
398 printf("Failed to initialize PSA Crypto\n");
399 return;
400 }
401
mohammad160387a7eeb2018-11-01 11:25:49 +0200402 /* Compute hash of message */
Jaeden Amero884738a2019-08-16 17:58:31 +0100403 status = psa_hash_setup(&operation, alg);
404 if (status != PSA_SUCCESS) {
405 printf("Failed to begin hash operation\n");
406 return;
407 }
408 status = psa_hash_update(&operation, input, sizeof(input));
409 if (status != PSA_SUCCESS) {
410 printf("Failed to update hash operation\n");
411 return;
412 }
413 status = psa_hash_finish(&operation, actual_hash, sizeof(actual_hash),
414 &actual_hash_len);
415 if (status != PSA_SUCCESS) {
416 printf("Failed to finish hash operation\n");
417 return;
418 }
419
420 printf("Hashed a message\n");
mohammad160387a7eeb2018-11-01 11:25:49 +0200421
422 /* Clean up hash operation context */
423 psa_hash_abort(&operation);
Jaeden Amero884738a2019-08-16 17:58:31 +0100424
425 mbedtls_psa_crypto_free();
mohammad160387a7eeb2018-11-01 11:25:49 +0200426```
427
Guy Wildc03c0fc2019-09-03 13:18:04 +0300428This example shows how to verify the `SHA-256` hash of a message:
mohammad160387a7eeb2018-11-01 11:25:49 +0200429```c
Jaeden Amero884738a2019-08-16 17:58:31 +0100430 psa_status_t status;
mohammad160387a7eeb2018-11-01 11:25:49 +0200431 psa_algorithm_t alg = PSA_ALG_SHA_256;
Jaeden Amero884738a2019-08-16 17:58:31 +0100432 psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
mohammad160387a7eeb2018-11-01 11:25:49 +0200433 unsigned char input[] = { 'a', 'b', 'c' };
434 unsigned char expected_hash[] = {
435 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, 0xde,
436 0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
437 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad
438 };
439 size_t expected_hash_len = PSA_HASH_SIZE(alg);
440
Jaeden Amero884738a2019-08-16 17:58:31 +0100441 printf("Verify a hash...\t");
442 fflush(stdout);
443
444 /* Initialize PSA Crypto */
445 status = psa_crypto_init();
446 if (status != PSA_SUCCESS) {
447 printf("Failed to initialize PSA Crypto\n");
448 return;
449 }
450
mohammad160387a7eeb2018-11-01 11:25:49 +0200451 /* Verify message hash */
Jaeden Amero884738a2019-08-16 17:58:31 +0100452 status = psa_hash_setup(&operation, alg);
453 if (status != PSA_SUCCESS) {
454 printf("Failed to begin hash operation\n");
455 return;
456 }
457 status = psa_hash_update(&operation, input, sizeof(input));
458 if (status != PSA_SUCCESS) {
459 printf("Failed to update hash operation\n");
460 return;
461 }
462 status = psa_hash_verify(&operation, expected_hash, expected_hash_len);
463 if (status != PSA_SUCCESS) {
464 printf("Failed to verify hash\n");
465 return;
466 }
467
468 printf("Verified a hash\n");
469
470 /* Clean up hash operation context */
471 psa_hash_abort(&operation);
472
473 mbedtls_psa_crypto_free();
mohammad160387a7eeb2018-11-01 11:25:49 +0200474```
475
476The API provides the macro `PSA_HASH_SIZE`, which returns the expected hash length (in bytes) for the specified algorithm.
477
478#### Handling hash operation contexts
479
Guy Wildc03c0fc2019-09-03 13:18:04 +0300480After 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 +0200481
Guy Wildc03c0fc2019-09-03 13:18:04 +0300482Mbed Crypto implicitly calls `psa_hash_abort()` when:
4831. A call to `psa_hash_update()` fails (returning any status other than `PSA_SUCCESS`).
4841. A call to `psa_hash_finish()` succeeds or fails.
4851. A call to `psa_hash_verify()` succeeds or fails.
mohammad160387a7eeb2018-11-01 11:25:49 +0200486
Guy Wildc03c0fc2019-09-03 13:18:04 +0300487After 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 +0200488
Guy Wildc03c0fc2019-09-03 13:18:04 +0300489You 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 +0200490
Guy Wildc03c0fc2019-09-03 13:18:04 +0300491Making 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 +0200492
493### Generating a random value
494
Guy Wildc03c0fc2019-09-03 13:18:04 +0300495Mbed Crypto can generate random data.
mohammad160387a7eeb2018-11-01 11:25:49 +0200496
Guy Wild802b19f2019-09-03 16:40:44 +0300497**Prerequisites to generating random data:**
Jaeden Amero884738a2019-08-16 17:58:31 +0100498* Initialize the library with a successful call to `psa_crypto_init()`.
mohammad160387a7eeb2018-11-01 11:25:49 +0200499
Guy Wild802b19f2019-09-03 16:40:44 +0300500<span class="notes">**Note:** To generate a random key, use `psa_generate_key()` instead of `psa_generate_random()`.</span>
501
502This example shows how to generate ten bytes of random data by calling `psa_generate_random()`:
mohammad160387a7eeb2018-11-01 11:25:49 +0200503```C
504 psa_status_t status;
505 uint8_t random[10] = { 0 };
mohammad160387a7eeb2018-11-01 11:25:49 +0200506
Jaeden Amero884738a2019-08-16 17:58:31 +0100507 printf("Generate random...\t");
508 fflush(stdout);
509
510 /* Initialize PSA Crypto */
511 status = psa_crypto_init();
512 if (status != PSA_SUCCESS) {
513 printf("Failed to initialize PSA Crypto\n");
514 return;
515 }
516
517 status = psa_generate_random(random, sizeof(random));
518 if (status != PSA_SUCCESS) {
519 printf("Failed to generate a random value\n");
520 return;
521 }
522
523 printf("Generated random data\n");
524
525 /* Clean up */
mohammad160387a7eeb2018-11-01 11:25:49 +0200526 mbedtls_psa_crypto_free();
527```
528
529### Deriving a new key from an existing key
530
Jaeden Amero884738a2019-08-16 17:58:31 +0100531Mbed Crypto provides a key derivation API that lets you derive new keys from
532existing ones. The key derivation API has functions to take inputs, including
533other keys and data, and functions to generate outputs, such as new keys or
Guy Wildc03c0fc2019-09-03 13:18:04 +0300534other data.
mohammad160387a7eeb2018-11-01 11:25:49 +0200535
Guy Wildc03c0fc2019-09-03 13:18:04 +0300536You must first initialize and set up a key derivation context,
537provided 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.
538
539See the documentation for the particular algorithm (such as HKDF or the TLS1.2 PRF) for
540information about which inputs to pass when, and when you can obtain which outputs.
541
542**Prerequisites to working with the key derivation APIs:**
543* Initialize the library with a successful call to `psa_crypto_init()`.
Jaeden Amero884738a2019-08-16 17:58:31 +0100544* Use a key with the appropriate attributes set:
545 * Usage flags set for key derivation (`PSA_KEY_USAGE_DERIVE`)
546 * Key type set to `PSA_KEY_TYPE_DERIVE`.
547 * Algorithm set to a key derivation algorithm
548 (`PSA_ALG_HKDF(PSA_ALG_SHA_256)`).
mohammad160387a7eeb2018-11-01 11:25:49 +0200549
Guy Wildc03c0fc2019-09-03 13:18:04 +0300550**To derive a new AES-CTR 128-bit encryption key into a given key slot using HKDF
551with a given key, salt and information:**
552
5531. Set up the key derivation context using the `psa_key_derivation_setup()`
Jaeden Amero884738a2019-08-16 17:58:31 +0100554function, specifying the derivation algorithm `PSA_ALG_HKDF(PSA_ALG_SHA_256)`.
Guy Wildc03c0fc2019-09-03 13:18:04 +03005551. Provide an optional salt with `psa_key_derivation_input_bytes()`.
Guy Wild802b19f2019-09-03 16:40:44 +03005561. Provide `info` with `psa_key_derivation_input_bytes()`.
5571. Provide `secret` with `psa_key_derivation_input_key()`, referencing a key that
Jaeden Amero884738a2019-08-16 17:58:31 +0100558 can be used for key derivation.
5591. Set the key attributes desired for the new derived key. We'll set
Guy Wildc03c0fc2019-09-03 13:18:04 +0300560 the `PSA_KEY_USAGE_ENCRYPT` parameter and the `PSA_ALG_CTR` algorithm for this
Jaeden Amero884738a2019-08-16 17:58:31 +0100561 example.
5621. Derive the key by calling `psa_key_derivation_output_key()`.
5631. Clean up the key derivation context.
mohammad160387a7eeb2018-11-01 11:25:49 +0200564
Guy Wildc03c0fc2019-09-03 13:18:04 +0300565At this point, the derived key slot holds a new 128-bit AES-CTR encryption key
566derived from the key, salt and information provided:
mohammad160387a7eeb2018-11-01 11:25:49 +0200567```C
Jaeden Amero884738a2019-08-16 17:58:31 +0100568 psa_status_t status;
569 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
570 static const unsigned char key[] = {
mohammad160387a7eeb2018-11-01 11:25:49 +0200571 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
572 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
573 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
574 0x0b };
Jaeden Amero884738a2019-08-16 17:58:31 +0100575 static const unsigned char salt[] = {
576 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
577 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c };
578 static const unsigned char info[] = {
579 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6,
580 0xf7, 0xf8, 0xf9 };
mohammad160387a7eeb2018-11-01 11:25:49 +0200581 psa_algorithm_t alg = PSA_ALG_HKDF(PSA_ALG_SHA_256);
Jaeden Amero884738a2019-08-16 17:58:31 +0100582 psa_key_derivation_operation_t operation =
583 PSA_KEY_DERIVATION_OPERATION_INIT;
mohammad160387a7eeb2018-11-01 11:25:49 +0200584 size_t derived_bits = 128;
585 size_t capacity = PSA_BITS_TO_BYTES(derived_bits);
Jaeden Amero884738a2019-08-16 17:58:31 +0100586 psa_key_handle_t base_key;
587 psa_key_handle_t derived_key;
mohammad160387a7eeb2018-11-01 11:25:49 +0200588
Jaeden Amero884738a2019-08-16 17:58:31 +0100589 printf("Derive a key (HKDF)...\t");
590 fflush(stdout);
591
592 /* Initialize PSA Crypto */
mohammad160387a7eeb2018-11-01 11:25:49 +0200593 status = psa_crypto_init();
Jaeden Amero884738a2019-08-16 17:58:31 +0100594 if (status != PSA_SUCCESS) {
595 printf("Failed to initialize PSA Crypto\n");
596 return;
597 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200598
Jaeden Amero884738a2019-08-16 17:58:31 +0100599 /* Import a key for use in key derivation. If such a key has already been
600 * generated or imported, you can skip this part. */
601 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE);
602 psa_set_key_algorithm(&attributes, alg);
603 psa_set_key_type(&attributes, PSA_KEY_TYPE_DERIVE);
604 status = psa_import_key(&attributes, key, sizeof(key), &base_key);
605 if (status != PSA_SUCCESS) {
606 printf("Failed to import a key\n");
607 return;
608 }
609 psa_reset_key_attributes(&attributes);
mohammad160387a7eeb2018-11-01 11:25:49 +0200610
Jaeden Amero884738a2019-08-16 17:58:31 +0100611 /* Derive a key */
612 status = psa_key_derivation_setup(&operation, alg);
613 if (status != PSA_SUCCESS) {
614 printf("Failed to begin key derivation\n");
615 return;
616 }
617 status = psa_key_derivation_set_capacity(&operation, capacity);
618 if (status != PSA_SUCCESS) {
619 printf("Failed to set capacity\n");
620 return;
621 }
622 status = psa_key_derivation_input_bytes(&operation,
623 PSA_KEY_DERIVATION_INPUT_SALT,
624 salt, sizeof(salt));
625 if (status != PSA_SUCCESS) {
626 printf("Failed to input salt (extract)\n");
627 return;
628 }
629 status = psa_key_derivation_input_key(&operation,
630 PSA_KEY_DERIVATION_INPUT_SECRET,
631 base_key);
632 if (status != PSA_SUCCESS) {
633 printf("Failed to input key (extract)\n");
634 return;
635 }
636 status = psa_key_derivation_input_bytes(&operation,
637 PSA_KEY_DERIVATION_INPUT_INFO,
638 info, sizeof(info));
639 if (status != PSA_SUCCESS) {
640 printf("Failed to input info (expand)\n");
641 return;
642 }
643 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
644 psa_set_key_algorithm(&attributes, PSA_ALG_CTR);
645 psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
646 psa_set_key_bits(&attributes, 128);
647 status = psa_key_derivation_output_key(&attributes, &operation,
648 &derived_key);
649 if (status != PSA_SUCCESS) {
650 printf("Failed to derive key\n");
651 return;
652 }
653 psa_reset_key_attributes(&attributes);
mohammad160387a7eeb2018-11-01 11:25:49 +0200654
Jaeden Amero884738a2019-08-16 17:58:31 +0100655 printf("Derived key\n");
mohammad160387a7eeb2018-11-01 11:25:49 +0200656
Jaeden Amero884738a2019-08-16 17:58:31 +0100657 /* Clean up key derivation operation */
658 psa_key_derivation_abort(&operation);
mohammad160387a7eeb2018-11-01 11:25:49 +0200659
Jaeden Amero884738a2019-08-16 17:58:31 +0100660 /* Destroy the keys */
661 psa_destroy_key(derived_key);
662 psa_destroy_key(base_key);
mohammad160387a7eeb2018-11-01 11:25:49 +0200663
mohammad160387a7eeb2018-11-01 11:25:49 +0200664 mbedtls_psa_crypto_free();
665```
666
667### Authenticating and encrypting or decrypting a message
668
Guy Wildc03c0fc2019-09-03 13:18:04 +0300669Mbed 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 +0200670
Guy Wildc03c0fc2019-09-03 13:18:04 +0300671**Prerequisites to working with the AEAD cipher APIs:**
672* Initialize the library with a successful call to `psa_crypto_init()`.
673* 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 +0200674
Guy Wildc03c0fc2019-09-03 13:18:04 +0300675This example shows how to authenticate and encrypt a message:
mohammad160387a7eeb2018-11-01 11:25:49 +0200676```C
mohammad160387a7eeb2018-11-01 11:25:49 +0200677 psa_status_t status;
Jaeden Amero884738a2019-08-16 17:58:31 +0100678 static const uint8_t key[] = {
679 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
680 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF };
681 static const uint8_t nonce[] = {
682 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
683 0x08, 0x09, 0x0A, 0x0B };
684 static const uint8_t additional_data[] = {
685 0xEC, 0x46, 0xBB, 0x63, 0xB0, 0x25,
686 0x20, 0xC3, 0x3C, 0x49, 0xFD, 0x70 };
687 static const uint8_t input_data[] = {
688 0xB9, 0x6B, 0x49, 0xE2, 0x1D, 0x62, 0x17, 0x41,
689 0x63, 0x28, 0x75, 0xDB, 0x7F, 0x6C, 0x92, 0x43,
690 0xD2, 0xD7, 0xC2 };
691 uint8_t *output_data = NULL;
mohammad160387a7eeb2018-11-01 11:25:49 +0200692 size_t output_size = 0;
693 size_t output_length = 0;
694 size_t tag_length = 16;
Jaeden Amero884738a2019-08-16 17:58:31 +0100695 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
696 psa_key_handle_t handle;
697
698 printf("Authenticate encrypt...\t");
699 fflush(stdout);
700
701 /* Initialize PSA Crypto */
702 status = psa_crypto_init();
703 if (status != PSA_SUCCESS) {
704 printf("Failed to initialize PSA Crypto\n");
705 return;
706 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200707
708 output_size = sizeof(input_data) + tag_length;
Jaeden Amero884738a2019-08-16 17:58:31 +0100709 output_data = (uint8_t *)malloc(output_size);
710 if (!output_data) {
711 printf("Out of memory\n");
712 return;
713 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200714
Jaeden Amero884738a2019-08-16 17:58:31 +0100715 /* Import a key */
716 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
717 psa_set_key_algorithm(&attributes, PSA_ALG_CCM);
718 psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
719 psa_set_key_bits(&attributes, 128);
720 status = psa_import_key(&attributes, key, sizeof(key), &handle);
721 psa_reset_key_attributes(&attributes);
mohammad160387a7eeb2018-11-01 11:25:49 +0200722
Jaeden Amero884738a2019-08-16 17:58:31 +0100723 /* Authenticate and encrypt */
724 status = psa_aead_encrypt(handle, PSA_ALG_CCM,
mohammad160387a7eeb2018-11-01 11:25:49 +0200725 nonce, sizeof(nonce),
726 additional_data, sizeof(additional_data),
727 input_data, sizeof(input_data),
728 output_data, output_size,
729 &output_length);
Jaeden Amero884738a2019-08-16 17:58:31 +0100730 if (status != PSA_SUCCESS) {
731 printf("Failed to authenticate and encrypt\n");
732 return;
733 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200734
Jaeden Amero884738a2019-08-16 17:58:31 +0100735 printf("Authenticated and encrypted\n");
736
737 /* Clean up */
738 free(output_data);
739
740 /* Destroy the key */
741 psa_destroy_key(handle);
742
mohammad160387a7eeb2018-11-01 11:25:49 +0200743 mbedtls_psa_crypto_free();
744```
745
Guy Wildc03c0fc2019-09-03 13:18:04 +0300746This example shows how to authenticate and decrypt a message:
mohammad160387a7eeb2018-11-01 11:25:49 +0200747
748```C
mohammad160387a7eeb2018-11-01 11:25:49 +0200749 psa_status_t status;
Jaeden Amero884738a2019-08-16 17:58:31 +0100750 static const uint8_t key[] = {
mohammad160387a7eeb2018-11-01 11:25:49 +0200751 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
Jaeden Amero884738a2019-08-16 17:58:31 +0100752 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF };
753 static const uint8_t nonce[] = {
754 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
755 0x08, 0x09, 0x0A, 0x0B };
756 static const uint8_t additional_data[] = {
757 0xEC, 0x46, 0xBB, 0x63, 0xB0, 0x25,
758 0x20, 0xC3, 0x3C, 0x49, 0xFD, 0x70 };
759 static const uint8_t input_data[] = {
760 0x20, 0x30, 0xE0, 0x36, 0xED, 0x09, 0xA0, 0x45, 0xAF, 0x3C, 0xBA, 0xEE,
761 0x0F, 0xC8, 0x48, 0xAF, 0xCD, 0x89, 0x54, 0xF4, 0xF6, 0x3F, 0x28, 0x9A,
762 0xA1, 0xDD, 0xB2, 0xB8, 0x09, 0xCD, 0x7C, 0xE1, 0x46, 0xE9, 0x98 };
763 uint8_t *output_data = NULL;
mohammad160387a7eeb2018-11-01 11:25:49 +0200764 size_t output_size = 0;
765 size_t output_length = 0;
Jaeden Amero884738a2019-08-16 17:58:31 +0100766 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
767 psa_key_handle_t handle;
768
769 printf("Authenticate decrypt...\t");
770 fflush(stdout);
771
772 /* Initialize PSA Crypto */
773 status = psa_crypto_init();
774 if (status != PSA_SUCCESS) {
775 printf("Failed to initialize PSA Crypto\n");
776 return;
777 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200778
779 output_size = sizeof(input_data);
Jaeden Amero884738a2019-08-16 17:58:31 +0100780 output_data = (uint8_t *)malloc(output_size);
781 if (!output_data) {
782 printf("Out of memory\n");
783 return;
784 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200785
Jaeden Amero884738a2019-08-16 17:58:31 +0100786 /* Import a key */
787 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT);
788 psa_set_key_algorithm(&attributes, PSA_ALG_CCM);
789 psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
790 psa_set_key_bits(&attributes, 128);
791 status = psa_import_key(&attributes, key, sizeof(key), &handle);
792 if (status != PSA_SUCCESS) {
793 printf("Failed to import a key\n");
794 return;
795 }
796 psa_reset_key_attributes(&attributes);
mohammad160387a7eeb2018-11-01 11:25:49 +0200797
Jaeden Amero884738a2019-08-16 17:58:31 +0100798 /* Authenticate and decrypt */
799 status = psa_aead_decrypt(handle, PSA_ALG_CCM,
mohammad160387a7eeb2018-11-01 11:25:49 +0200800 nonce, sizeof(nonce),
801 additional_data, sizeof(additional_data),
802 input_data, sizeof(input_data),
803 output_data, output_size,
804 &output_length);
Jaeden Amero884738a2019-08-16 17:58:31 +0100805 if (status != PSA_SUCCESS) {
806 printf("Failed to authenticate and decrypt %ld\n", status);
807 return;
808 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200809
Jaeden Amero884738a2019-08-16 17:58:31 +0100810 printf("Authenticated and decrypted\n");
811
812 /* Clean up */
813 free(output_data);
814
815 /* Destroy the key */
816 psa_destroy_key(handle);
817
mohammad160387a7eeb2018-11-01 11:25:49 +0200818 mbedtls_psa_crypto_free();
819```
820
821### Generating and exporting keys
822
823Mbed Crypto provides a simple way to generate a key or key pair.
824
Guy Wildc03c0fc2019-09-03 13:18:04 +0300825**Prerequisites to using key generation and export APIs:**
826* Initialize the library with a successful call to `psa_crypto_init()`.
mohammad160387a7eeb2018-11-01 11:25:49 +0200827
Guy Wildc03c0fc2019-09-03 13:18:04 +0300828**To generate an ECDSA key:**
Jaeden Amero884738a2019-08-16 17:58:31 +01008291. Set the desired key attributes for key generation by calling
830 `psa_set_key_algorithm()` with the chosen ECDSA algorithm (such as
Guy Wildc03c0fc2019-09-03 13:18:04 +0300831 `PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256)`). Do not set
Guy Wild802b19f2019-09-03 16:40:44 +0300832 `PSA_KEY_USAGE_EXPORT`; we only want to export the public key, not the key
Jaeden Amero884738a2019-08-16 17:58:31 +0100833 pair (or private key).
8341. Generate a key by calling `psa_generate_key()`.
Guy Wildc03c0fc2019-09-03 13:18:04 +03008351. Export the generated public key by calling `psa_export_public_key()`:
mohammad160387a7eeb2018-11-01 11:25:49 +0200836```C
Jaeden Amero884738a2019-08-16 17:58:31 +0100837 enum {
838 key_bits = 256,
839 };
840 psa_status_t status;
mohammad160387a7eeb2018-11-01 11:25:49 +0200841 size_t exported_length = 0;
Jaeden Amero884738a2019-08-16 17:58:31 +0100842 static uint8_t exported[PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits)];
843 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
844 psa_key_handle_t handle;
mohammad160387a7eeb2018-11-01 11:25:49 +0200845
Jaeden Amero884738a2019-08-16 17:58:31 +0100846 printf("Generate a key pair...\t");
847 fflush(stdout);
mohammad160387a7eeb2018-11-01 11:25:49 +0200848
Jaeden Amero884738a2019-08-16 17:58:31 +0100849 /* Initialize PSA Crypto */
850 status = psa_crypto_init();
851 if (status != PSA_SUCCESS) {
852 printf("Failed to initialize PSA Crypto\n");
853 return;
854 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200855
856 /* Generate a key */
Jaeden Amero884738a2019-08-16 17:58:31 +0100857 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN);
858 psa_set_key_algorithm(&attributes,
859 PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256));
860 psa_set_key_type(&attributes,
861 PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1));
862 psa_set_key_bits(&attributes, key_bits);
863 status = psa_generate_key(&attributes, &handle);
864 if (status != PSA_SUCCESS) {
865 printf("Failed to generate key\n");
866 return;
867 }
868 psa_reset_key_attributes(&attributes);
mohammad160387a7eeb2018-11-01 11:25:49 +0200869
Jaeden Amero884738a2019-08-16 17:58:31 +0100870 status = psa_export_public_key(handle, exported, sizeof(exported),
871 &exported_length);
872 if (status != PSA_SUCCESS) {
873 printf("Failed to export public key %ld\n", status);
874 return;
875 }
mohammad160387a7eeb2018-11-01 11:25:49 +0200876
Jaeden Amero884738a2019-08-16 17:58:31 +0100877 printf("Exported a public key\n");
878
879 /* Destroy the key */
880 psa_destroy_key(handle);
881
mohammad160387a7eeb2018-11-01 11:25:49 +0200882 mbedtls_psa_crypto_free();
883```
884
Guy Wild802b19f2019-09-03 16:40:44 +0300885### More about the Mbed Crypto API
mohammad160387a7eeb2018-11-01 11:25:49 +0200886
Guy Wildc03c0fc2019-09-03 13:18:04 +0300887For 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).