Skip to content

Commit 55380c6

Browse files
authored
Merge pull request #2 from ARMmbed/mbed-crypto-examples
Mbed Crypto examples on Mbed OS
2 parents adc6702 + 093184e commit 55380c6

File tree

5 files changed

+394
-1
lines changed

5 files changed

+394
-1
lines changed

README.md

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,40 @@
1-
# mbed-os-example-mbed-crypto
1+
# Running Mbed Crypto examples on Mbed OS
2+
This repository contains a set of examples demonstrating the compilation and use
3+
of Mbed Crypto on Mbed OS.
24

5+
List of examples contained within this repository:
6+
* Cipher encrypt/decrypt using an AES key in cipher block chain (CBC) mode with no padding using a single block.
7+
* Cipher encrypt/decrypt using an AES key in cipher block chain (CBC) mode with PKCS7 padding using multiple blocks.
8+
* Cipher encrypt/decrypt using an AES key in counter (CTR) mode using multiple blocks.
9+
10+
## Prerequisites
11+
* Install <a href='https://github.com/ARMmbed/mbed-cli#installing-mbed-cli'>Mbed CLI</a>
12+
13+
## Deploy
14+
The following are the steps required for deployment:
15+
* Clone this repository: `git clone [email protected]:ARMmbed/mbed-os-example-mbed-crypto.git`
16+
* Change your current directory: `cd mbed-os-example-mbed-crypto`
17+
* Fetch Mbed OS: `mbed deploy`
18+
19+
## Compile
20+
To compile the example program use `mbed compile` while specifying the target platform and the compiler.
21+
For example, in order to compile using the ARM GCC compiler and a K64F target platform use: `mbed compile -m K64F -t ARM`.
22+
23+
Once the compilation is completed successfully a binary file will be created: `./BUILD/K64F/GCC_ARM/mbed-os-example-mbed-crypto.bin`
24+
25+
## Run
26+
The following are the steps required to run the example program:
27+
* Connect the Mbed device to your computer over USB.
28+
* Copy the binary file (`mbed-os-example-mbed-crypto.bin`) to the Mbed device.
29+
* Connect to the Mbed Device using a serial client application of your choice.
30+
* Press the reset button on the Mbed device to run the program.
31+
32+
The expected output from a successful execution of the example program should be as follows:
33+
```
34+
cipher encrypt/decrypt AES CBC no padding:
35+
success!
36+
cipher encrypt/decrypt AES CBC PKCS7 multipart:
37+
success!
38+
cipher encrypt/decrypt AES CTR multipart:
39+
success!
40+
```

main.cpp

Lines changed: 340 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,340 @@
1+
/*
2+
* Copyright (c) 2018, Arm Limited and affiliates
3+
* SPDX-License-Identifier: Apache-2.0
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
#include "psa/crypto.h"
19+
#include <string.h>
20+
#include <inttypes.h>
21+
22+
#if defined(MBEDTLS_PLATFORM_C)
23+
#include "mbedtls/platform.h"
24+
#else
25+
#include <stdio.h>
26+
#define mbedtls_printf printf
27+
#endif
28+
29+
#define ASSERT_STATUS(actual, expected) \
30+
do \
31+
{ \
32+
if((actual) != (expected)) \
33+
{ \
34+
mbedtls_printf( "\tassertion failed at %s:%d - " \
35+
"actual:%" PRId32 "expected:%" PRId32 "\n", \
36+
__FILE__, __LINE__, \
37+
(psa_status_t) actual, (psa_status_t) expected ); \
38+
goto exit; \
39+
} \
40+
} while (0)
41+
42+
#if !defined(MBEDTLS_PSA_CRYPTO_C) || !defined(MBEDTLS_AES_C) || \
43+
!defined(MBEDTLS_CIPHER_MODE_CBC) || !defined(MBEDTLS_CIPHER_MODE_CTR) || \
44+
!defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
45+
int main(void)
46+
{
47+
mbedtls_printf("Not all of the required options are defined:\n"
48+
" - MBEDTLS_PSA_CRYPTO_C\n"
49+
" - MBEDTLS_AES_C\n"
50+
" - MBEDTLS_CIPHER_MODE_CBC\n"
51+
" - MBEDTLS_CIPHER_MODE_CTR\n"
52+
" - MBEDTLS_CIPHER_MODE_WITH_PADDING\n");
53+
return 0;
54+
}
55+
#else
56+
57+
/* Use key slot 1 for our cipher key. Key slot 0 is reserved as unused. */
58+
static const psa_key_slot_t key_slot_cipher = 1;
59+
60+
static psa_status_t set_key_policy(psa_key_slot_t key_slot,
61+
psa_key_usage_t key_usage,
62+
psa_algorithm_t alg)
63+
{
64+
psa_status_t status;
65+
psa_key_policy_t policy;
66+
67+
psa_key_policy_init(&policy);
68+
psa_key_policy_set_usage(&policy, key_usage, alg);
69+
status = psa_set_key_policy(key_slot, &policy);
70+
ASSERT_STATUS(status, PSA_SUCCESS);
71+
exit:
72+
return status;
73+
}
74+
75+
static psa_status_t cipher_operation(psa_cipher_operation_t *operation,
76+
const uint8_t *input,
77+
size_t input_size,
78+
size_t part_size,
79+
uint8_t *output,
80+
size_t output_size,
81+
size_t *output_len)
82+
{
83+
psa_status_t status;
84+
size_t bytes_to_write = 0, bytes_written = 0, len = 0;
85+
86+
*output_len = 0;
87+
while (bytes_written != input_size) {
88+
bytes_to_write = (input_size - bytes_written > part_size ?
89+
part_size :
90+
input_size - bytes_written);
91+
92+
status = psa_cipher_update(operation, input + bytes_written,
93+
bytes_to_write, output + *output_len,
94+
output_size - *output_len, &len);
95+
ASSERT_STATUS(status, PSA_SUCCESS);
96+
97+
bytes_written += bytes_to_write;
98+
*output_len += len;
99+
}
100+
101+
status = psa_cipher_finish(operation, output + *output_len,
102+
output_size - *output_len, &len);
103+
ASSERT_STATUS(status, PSA_SUCCESS);
104+
*output_len += len;
105+
106+
exit:
107+
return status;
108+
}
109+
110+
static psa_status_t cipher_encrypt(psa_key_slot_t key_slot,
111+
psa_algorithm_t alg,
112+
uint8_t *iv,
113+
size_t iv_size,
114+
const uint8_t *input,
115+
size_t input_size,
116+
size_t part_size,
117+
uint8_t *output,
118+
size_t output_size,
119+
size_t *output_len)
120+
{
121+
psa_status_t status;
122+
psa_cipher_operation_t operation;
123+
size_t iv_len = 0;
124+
125+
memset(&operation, 0, sizeof(operation));
126+
status = psa_cipher_encrypt_setup(&operation, key_slot, alg);
127+
ASSERT_STATUS(status, PSA_SUCCESS);
128+
129+
status = psa_cipher_generate_iv(&operation, iv, iv_size, &iv_len);
130+
ASSERT_STATUS(status, PSA_SUCCESS);
131+
132+
status = cipher_operation(&operation, input, input_size, part_size,
133+
output, output_size, output_len);
134+
ASSERT_STATUS(status, PSA_SUCCESS);
135+
136+
exit:
137+
psa_cipher_abort(&operation);
138+
return status;
139+
}
140+
141+
static psa_status_t cipher_decrypt(psa_key_slot_t key_slot,
142+
psa_algorithm_t alg,
143+
const uint8_t *iv,
144+
size_t iv_size,
145+
const uint8_t *input,
146+
size_t input_size,
147+
size_t part_size,
148+
uint8_t *output,
149+
size_t output_size,
150+
size_t *output_len)
151+
{
152+
psa_status_t status;
153+
psa_cipher_operation_t operation;
154+
155+
memset(&operation, 0, sizeof(operation));
156+
status = psa_cipher_decrypt_setup(&operation, key_slot, alg);
157+
ASSERT_STATUS(status, PSA_SUCCESS);
158+
159+
status = psa_cipher_set_iv(&operation, iv, iv_size);
160+
ASSERT_STATUS(status, PSA_SUCCESS);
161+
162+
status = cipher_operation(&operation, input, input_size, part_size,
163+
output, output_size, output_len);
164+
ASSERT_STATUS(status, PSA_SUCCESS);
165+
166+
exit:
167+
psa_cipher_abort(&operation);
168+
return status;
169+
}
170+
171+
static psa_status_t cipher_example_encrypt_decrypt_aes_cbc_nopad_1_block(void)
172+
{
173+
enum {
174+
block_size = PSA_BLOCK_CIPHER_BLOCK_SIZE(PSA_KEY_TYPE_AES),
175+
key_bits = 256,
176+
part_size = block_size,
177+
};
178+
const psa_algorithm_t alg = PSA_ALG_CBC_NO_PADDING;
179+
180+
psa_status_t status;
181+
size_t output_len = 0;
182+
uint8_t iv[block_size];
183+
uint8_t input[block_size];
184+
uint8_t encrypt[block_size];
185+
uint8_t decrypt[block_size];
186+
187+
status = psa_generate_random(input, sizeof(input));
188+
ASSERT_STATUS(status, PSA_SUCCESS);
189+
190+
status = set_key_policy(key_slot_cipher,
191+
PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT,
192+
alg);
193+
ASSERT_STATUS(status, PSA_SUCCESS);
194+
195+
status = psa_generate_key(key_slot_cipher, PSA_KEY_TYPE_AES, key_bits,
196+
NULL, 0);
197+
ASSERT_STATUS(status, PSA_SUCCESS);
198+
199+
status = cipher_encrypt(key_slot_cipher, alg, iv, sizeof(iv),
200+
input, sizeof(input), part_size,
201+
encrypt, sizeof(encrypt), &output_len);
202+
ASSERT_STATUS(status, PSA_SUCCESS);
203+
204+
status = cipher_decrypt(key_slot_cipher, alg, iv, sizeof(iv),
205+
encrypt, output_len, part_size,
206+
decrypt, sizeof(decrypt), &output_len);
207+
ASSERT_STATUS(status, PSA_SUCCESS);
208+
209+
status = memcmp(input, decrypt, sizeof(input));
210+
ASSERT_STATUS(status, PSA_SUCCESS);
211+
212+
exit:
213+
psa_destroy_key(key_slot_cipher);
214+
return status;
215+
}
216+
217+
static psa_status_t cipher_example_encrypt_decrypt_aes_cbc_pkcs7_multi(void)
218+
{
219+
enum {
220+
block_size = PSA_BLOCK_CIPHER_BLOCK_SIZE(PSA_KEY_TYPE_AES),
221+
key_bits = 256,
222+
input_size = 100,
223+
part_size = 10,
224+
};
225+
226+
const psa_algorithm_t alg = PSA_ALG_CBC_PKCS7;
227+
228+
psa_status_t status;
229+
size_t output_len = 0;
230+
uint8_t iv[block_size], input[input_size],
231+
encrypt[input_size + block_size], decrypt[input_size + block_size];
232+
233+
status = psa_generate_random(input, sizeof(input));
234+
ASSERT_STATUS(status, PSA_SUCCESS);
235+
236+
status = set_key_policy(key_slot_cipher,
237+
PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT,
238+
alg);
239+
ASSERT_STATUS(status, PSA_SUCCESS);
240+
241+
status = psa_generate_key(key_slot_cipher, PSA_KEY_TYPE_AES, key_bits,
242+
NULL, 0);
243+
ASSERT_STATUS(status, PSA_SUCCESS);
244+
245+
status = cipher_encrypt(key_slot_cipher, alg, iv, sizeof(iv),
246+
input, sizeof(input), part_size,
247+
encrypt, sizeof(encrypt), &output_len);
248+
ASSERT_STATUS(status, PSA_SUCCESS);
249+
250+
status = cipher_decrypt(key_slot_cipher, alg, iv, sizeof(iv),
251+
encrypt, output_len, part_size,
252+
decrypt, sizeof(decrypt), &output_len);
253+
ASSERT_STATUS(status, PSA_SUCCESS);
254+
255+
status = memcmp(input, decrypt, sizeof(input));
256+
ASSERT_STATUS(status, PSA_SUCCESS);
257+
258+
exit:
259+
psa_destroy_key(key_slot_cipher);
260+
return status;
261+
}
262+
263+
static psa_status_t cipher_example_encrypt_decrypt_aes_ctr_multi(void)
264+
{
265+
enum {
266+
block_size = PSA_BLOCK_CIPHER_BLOCK_SIZE(PSA_KEY_TYPE_AES),
267+
key_bits = 256,
268+
input_size = 100,
269+
part_size = 10,
270+
};
271+
const psa_algorithm_t alg = PSA_ALG_CTR;
272+
273+
psa_status_t status;
274+
size_t output_len = 0;
275+
uint8_t iv[block_size], input[input_size], encrypt[input_size],
276+
decrypt[input_size];
277+
278+
status = psa_generate_random(input, sizeof(input));
279+
ASSERT_STATUS(status, PSA_SUCCESS);
280+
281+
status = set_key_policy(key_slot_cipher,
282+
PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT,
283+
alg);
284+
ASSERT_STATUS(status, PSA_SUCCESS);
285+
286+
status = psa_generate_key(key_slot_cipher, PSA_KEY_TYPE_AES, key_bits,
287+
NULL, 0);
288+
ASSERT_STATUS(status, PSA_SUCCESS);
289+
290+
status = cipher_encrypt(key_slot_cipher, alg, iv, sizeof(iv),
291+
input, sizeof(input), part_size,
292+
encrypt, sizeof(encrypt), &output_len);
293+
ASSERT_STATUS(status, PSA_SUCCESS);
294+
295+
status = cipher_decrypt(key_slot_cipher, alg, iv, sizeof(iv),
296+
encrypt, output_len, part_size,
297+
decrypt, sizeof(decrypt), &output_len);
298+
ASSERT_STATUS(status, PSA_SUCCESS);
299+
300+
status = memcmp(input, decrypt, sizeof(input));
301+
ASSERT_STATUS(status, PSA_SUCCESS);
302+
303+
exit:
304+
psa_destroy_key(key_slot_cipher);
305+
return status;
306+
}
307+
308+
static void cipher_examples(void)
309+
{
310+
psa_status_t status;
311+
312+
mbedtls_printf("cipher encrypt/decrypt AES CBC no padding:\n");
313+
status = cipher_example_encrypt_decrypt_aes_cbc_nopad_1_block();
314+
if (status == PSA_SUCCESS) {
315+
mbedtls_printf("\tsuccess!\n");
316+
}
317+
318+
mbedtls_printf("cipher encrypt/decrypt AES CBC PKCS7 multipart:\n");
319+
status = cipher_example_encrypt_decrypt_aes_cbc_pkcs7_multi();
320+
if (status == PSA_SUCCESS) {
321+
mbedtls_printf("\tsuccess!\n");
322+
}
323+
324+
mbedtls_printf("cipher encrypt/decrypt AES CTR multipart:\n");
325+
status = cipher_example_encrypt_decrypt_aes_ctr_multi();
326+
if (status == PSA_SUCCESS) {
327+
mbedtls_printf("\tsuccess!\n");
328+
}
329+
}
330+
331+
int main(void)
332+
{
333+
ASSERT_STATUS(psa_crypto_init(), PSA_SUCCESS);
334+
cipher_examples();
335+
exit:
336+
mbedtls_psa_crypto_free();
337+
return 0;
338+
}
339+
#endif /* MBEDTLS_PSA_CRYPTO_C && MBEDTLS_AES_C && MBEDTLS_CIPHER_MODE_CBC &&
340+
MBEDTLS_CIPHER_MODE_CTR && MBEDTLS_CIPHER_MODE_WITH_PADDING */

main.log

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
cipher encrypt/decrypt AES CBC no padding:
2+
success!
3+
cipher encrypt/decrypt AES CBC PKCS7 multipart:
4+
success!
5+
cipher encrypt/decrypt AES CTR multipart:
6+
success!

mbed-os.lib

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
https://github.com/mohammad1603/mbed-os/#606cf41ba383c4ea5673082b536848fa5b4e0dbe

0 commit comments

Comments
 (0)