Hello world example of using the authenticated encryption with mbed TLS. The canonical source for this example lives at https://github.com/ARMmbed/mbed-os-example-tls

mbed TLS Benchmark example on mbed OS

This application performs authenticated encryption and authenticated decryption of a buffer. It serves as a tutorial for the basic authenticated encryption functions of mbed TLS.

Getting started

Building with mbed CLI

If you'd like to use mbed CLI to build this, then you should set up your environment if you have not done so already. For instructions, refer to the main readme. The instructions on this page relate to using the developer.mbed.org Online Compiler

Import the program in to the Online Compiler, select your board from the drop down in the top right hand corner and then compile the application. Once it has built, you can drag and drop the binary onto your device.

Monitoring the application

The output in the terminal window should be similar to this:

terminal output

plaintext message: 536f6d65207468696e67732061726520626574746572206c65667420756e7265616400
ciphertext: c57f7afb94f14c7977d785d08682a2596bd62ee9dcf216b8cccd997afee9b402f5de1739e8e6467aa363749ef39392e5c66622b01c7203ec0a3d14
decrypted: 536f6d65207468696e67732061726520626574746572206c65667420756e7265616400

DONE
Committer:
Janos Follath
Date:
Wed Jul 27 14:18:25 2016 +0100
Revision:
0:9a918c8d34dc
Child:
5:97e046e0e2b1
Update example home repo at https://github.com/ARMmbed/mbed-os-example-tls

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Janos Follath 0:9a918c8d34dc 1 /*
Janos Follath 0:9a918c8d34dc 2 * Hello world example of using the authenticated encryption with mbed TLS
Janos Follath 0:9a918c8d34dc 3 *
Janos Follath 0:9a918c8d34dc 4 * Copyright (C) 2016, ARM Limited, All Rights Reserved
Janos Follath 0:9a918c8d34dc 5 * SPDX-License-Identifier: Apache-2.0
Janos Follath 0:9a918c8d34dc 6 *
Janos Follath 0:9a918c8d34dc 7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
Janos Follath 0:9a918c8d34dc 8 * not use this file except in compliance with the License.
Janos Follath 0:9a918c8d34dc 9 * You may obtain a copy of the License at
Janos Follath 0:9a918c8d34dc 10 *
Janos Follath 0:9a918c8d34dc 11 * http://www.apache.org/licenses/LICENSE-2.0
Janos Follath 0:9a918c8d34dc 12 *
Janos Follath 0:9a918c8d34dc 13 * Unless required by applicable law or agreed to in writing, software
Janos Follath 0:9a918c8d34dc 14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
Janos Follath 0:9a918c8d34dc 15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Janos Follath 0:9a918c8d34dc 16 * See the License for the specific language governing permissions and
Janos Follath 0:9a918c8d34dc 17 * limitations under the License.
Janos Follath 0:9a918c8d34dc 18 */
Janos Follath 0:9a918c8d34dc 19
Janos Follath 0:9a918c8d34dc 20 #include "mbed.h"
Janos Follath 0:9a918c8d34dc 21
Janos Follath 0:9a918c8d34dc 22 #include "mbedtls/cipher.h"
Janos Follath 0:9a918c8d34dc 23 #include "mbedtls/entropy.h"
Janos Follath 0:9a918c8d34dc 24 #include "mbedtls/ctr_drbg.h"
Janos Follath 0:9a918c8d34dc 25 #if DEBUG_LEVEL > 0
Janos Follath 0:9a918c8d34dc 26 #include "mbedtls/debug.h"
Janos Follath 0:9a918c8d34dc 27 #endif
Janos Follath 0:9a918c8d34dc 28
Janos Follath 0:9a918c8d34dc 29 #include "mbedtls/platform.h"
Janos Follath 0:9a918c8d34dc 30
Janos Follath 0:9a918c8d34dc 31 #include <string.h>
Janos Follath 0:9a918c8d34dc 32
Janos Follath 0:9a918c8d34dc 33 static void print_hex(const char *title, const unsigned char buf[], size_t len)
Janos Follath 0:9a918c8d34dc 34 {
Janos Follath 0:9a918c8d34dc 35 mbedtls_printf("%s: ", title);
Janos Follath 0:9a918c8d34dc 36
Janos Follath 0:9a918c8d34dc 37 for (size_t i = 0; i < len; i++)
Janos Follath 0:9a918c8d34dc 38 mbedtls_printf("%02x", buf[i]);
Janos Follath 0:9a918c8d34dc 39
Janos Follath 0:9a918c8d34dc 40 mbedtls_printf("\r\n");
Janos Follath 0:9a918c8d34dc 41 }
Janos Follath 0:9a918c8d34dc 42
Janos Follath 0:9a918c8d34dc 43 /*
Janos Follath 0:9a918c8d34dc 44 * The pre-shared key. Should be generated randomly and be unique to the
Janos Follath 0:9a918c8d34dc 45 * device/channel/etc. Just used a fixed on here for simplicity.
Janos Follath 0:9a918c8d34dc 46 */
Janos Follath 0:9a918c8d34dc 47 static const unsigned char secret_key[16] = {
Janos Follath 0:9a918c8d34dc 48 0xf4, 0x82, 0xc6, 0x70, 0x3c, 0xc7, 0x61, 0x0a,
Janos Follath 0:9a918c8d34dc 49 0xb9, 0xa0, 0xb8, 0xe9, 0x87, 0xb8, 0xc1, 0x72,
Janos Follath 0:9a918c8d34dc 50 };
Janos Follath 0:9a918c8d34dc 51
Janos Follath 0:9a918c8d34dc 52 static int example(void)
Janos Follath 0:9a918c8d34dc 53 {
Janos Follath 0:9a918c8d34dc 54 /* message that should be protected */
Janos Follath 0:9a918c8d34dc 55 const char message[] = "Some things are better left unread";
Janos Follath 0:9a918c8d34dc 56 /* metadata transmitted in the clear but authenticated */
Janos Follath 0:9a918c8d34dc 57 const char metadata[] = "eg sequence number, routing info";
Janos Follath 0:9a918c8d34dc 58 /* ciphertext buffer large enough to hold message + nonce + tag */
Janos Follath 0:9a918c8d34dc 59 unsigned char ciphertext[128] = { 0 };
Janos Follath 0:9a918c8d34dc 60 int ret;
Janos Follath 0:9a918c8d34dc 61
Janos Follath 0:9a918c8d34dc 62 mbedtls_printf("\r\n\r\n");
Janos Follath 0:9a918c8d34dc 63 print_hex("plaintext message", (unsigned char *) message, sizeof message);
Janos Follath 0:9a918c8d34dc 64
Janos Follath 0:9a918c8d34dc 65 /*
Janos Follath 0:9a918c8d34dc 66 * Setup random number generator
Janos Follath 0:9a918c8d34dc 67 * (Note: later this might be done automatically.)
Janos Follath 0:9a918c8d34dc 68 */
Janos Follath 0:9a918c8d34dc 69 mbedtls_entropy_context entropy; /* entropy pool for seeding PRNG */
Janos Follath 0:9a918c8d34dc 70 mbedtls_ctr_drbg_context drbg; /* pseudo-random generator */
Janos Follath 0:9a918c8d34dc 71
Janos Follath 0:9a918c8d34dc 72 mbedtls_entropy_init(&entropy);
Janos Follath 0:9a918c8d34dc 73 mbedtls_ctr_drbg_init(&drbg);
Janos Follath 0:9a918c8d34dc 74
Janos Follath 0:9a918c8d34dc 75 /* Seed the PRNG using the entropy pool, and throw in our secret key as an
Janos Follath 0:9a918c8d34dc 76 * additional source of randomness. */
Janos Follath 0:9a918c8d34dc 77 ret = mbedtls_ctr_drbg_seed(&drbg, mbedtls_entropy_func, &entropy,
Janos Follath 0:9a918c8d34dc 78 secret_key, sizeof secret_key);
Janos Follath 0:9a918c8d34dc 79 if (ret != 0) {
Janos Follath 0:9a918c8d34dc 80 return 1;
Janos Follath 0:9a918c8d34dc 81 }
Janos Follath 0:9a918c8d34dc 82
Janos Follath 0:9a918c8d34dc 83 /*
Janos Follath 0:9a918c8d34dc 84 * Setup AES-CCM contex
Janos Follath 0:9a918c8d34dc 85 */
Janos Follath 0:9a918c8d34dc 86 mbedtls_cipher_context_t ctx;
Janos Follath 0:9a918c8d34dc 87
Janos Follath 0:9a918c8d34dc 88 mbedtls_cipher_init(&ctx);
Janos Follath 0:9a918c8d34dc 89
Janos Follath 0:9a918c8d34dc 90 ret = mbedtls_cipher_setup(&ctx, mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_CCM));
Janos Follath 0:9a918c8d34dc 91 if (ret != 0) {
Janos Follath 0:9a918c8d34dc 92 mbedtls_printf("mbedtls_cipher_setup() returned -0x%04X\r\n", -ret);
Janos Follath 0:9a918c8d34dc 93 return 1;
Janos Follath 0:9a918c8d34dc 94 }
Janos Follath 0:9a918c8d34dc 95
Janos Follath 0:9a918c8d34dc 96 ret = mbedtls_cipher_setkey(&ctx, secret_key, 8 * sizeof secret_key, MBEDTLS_ENCRYPT);
Janos Follath 0:9a918c8d34dc 97 if (ret != 0) {
Janos Follath 0:9a918c8d34dc 98 mbedtls_printf("mbedtls_cipher_setkey() returned -0x%04X\r\n", -ret);
Janos Follath 0:9a918c8d34dc 99 return 1;
Janos Follath 0:9a918c8d34dc 100 }
Janos Follath 0:9a918c8d34dc 101
Janos Follath 0:9a918c8d34dc 102 /*
Janos Follath 0:9a918c8d34dc 103 * Encrypt-authenticate the message and authenticate additional data
Janos Follath 0:9a918c8d34dc 104 *
Janos Follath 0:9a918c8d34dc 105 * First generate a random 8-byte nonce.
Janos Follath 0:9a918c8d34dc 106 * Put it directly in the output buffer as the recipient will need it.
Janos Follath 0:9a918c8d34dc 107 *
Janos Follath 0:9a918c8d34dc 108 * Warning: you must never re-use the same (key, nonce) pair. One of the
Janos Follath 0:9a918c8d34dc 109 * best ways to ensure this to use a counter for the nonce. However this
Janos Follath 0:9a918c8d34dc 110 * means you should save the counter accross rebots, if the key is a
Janos Follath 0:9a918c8d34dc 111 * long-term one. The alternative we choose here is to generate the nonce
Janos Follath 0:9a918c8d34dc 112 * randomly. However it only works if you have a good source of
Janos Follath 0:9a918c8d34dc 113 * randomness.
Janos Follath 0:9a918c8d34dc 114 */
Janos Follath 0:9a918c8d34dc 115 const size_t nonce_len = 8;
Janos Follath 0:9a918c8d34dc 116 mbedtls_ctr_drbg_random(&drbg, ciphertext, nonce_len);
Janos Follath 0:9a918c8d34dc 117
Janos Follath 0:9a918c8d34dc 118 size_t ciphertext_len = 0;
Janos Follath 0:9a918c8d34dc 119 /* Go for a conservative 16-byte (128-bit) tag
Janos Follath 0:9a918c8d34dc 120 * and append it to the ciphertext */
Janos Follath 0:9a918c8d34dc 121 const size_t tag_len = 16;
Janos Follath 0:9a918c8d34dc 122 ret = mbedtls_cipher_auth_encrypt(&ctx, ciphertext, nonce_len,
Janos Follath 0:9a918c8d34dc 123 (const unsigned char *) metadata, sizeof metadata,
Janos Follath 0:9a918c8d34dc 124 (const unsigned char *) message, sizeof message,
Janos Follath 0:9a918c8d34dc 125 ciphertext + nonce_len, &ciphertext_len,
Janos Follath 0:9a918c8d34dc 126 ciphertext + nonce_len + sizeof message, tag_len );
Janos Follath 0:9a918c8d34dc 127 if (ret != 0) {
Janos Follath 0:9a918c8d34dc 128 mbedtls_printf("mbedtls_cipher_auth_encrypt() returned -0x%04X\r\n", -ret);
Janos Follath 0:9a918c8d34dc 129 return 1;
Janos Follath 0:9a918c8d34dc 130 }
Janos Follath 0:9a918c8d34dc 131 ciphertext_len += nonce_len + tag_len;
Janos Follath 0:9a918c8d34dc 132
Janos Follath 0:9a918c8d34dc 133 /*
Janos Follath 0:9a918c8d34dc 134 * The following information should now be transmitted:
Janos Follath 0:9a918c8d34dc 135 * - first ciphertext_len bytes of ciphertext buffer
Janos Follath 0:9a918c8d34dc 136 * - metadata if not already transmitted elsewhere
Janos Follath 0:9a918c8d34dc 137 */
Janos Follath 0:9a918c8d34dc 138 print_hex("ciphertext", ciphertext, ciphertext_len);
Janos Follath 0:9a918c8d34dc 139
Janos Follath 0:9a918c8d34dc 140 /*
Janos Follath 0:9a918c8d34dc 141 * Decrypt-authenticate
Janos Follath 0:9a918c8d34dc 142 */
Janos Follath 0:9a918c8d34dc 143 unsigned char decrypted[128] = { 0 };
Janos Follath 0:9a918c8d34dc 144 size_t decrypted_len = 0;
Janos Follath 0:9a918c8d34dc 145
Janos Follath 0:9a918c8d34dc 146 ret = mbedtls_cipher_setkey(&ctx, secret_key, 8 * sizeof secret_key, MBEDTLS_DECRYPT);
Janos Follath 0:9a918c8d34dc 147 if (ret != 0) {
Janos Follath 0:9a918c8d34dc 148 mbedtls_printf("mbedtls_cipher_setkey() returned -0x%04X\r\n", -ret);
Janos Follath 0:9a918c8d34dc 149 return 1;
Janos Follath 0:9a918c8d34dc 150 }
Janos Follath 0:9a918c8d34dc 151
Janos Follath 0:9a918c8d34dc 152 ret = mbedtls_cipher_auth_decrypt(&ctx,
Janos Follath 0:9a918c8d34dc 153 ciphertext, nonce_len,
Janos Follath 0:9a918c8d34dc 154 (const unsigned char *) metadata, sizeof metadata,
Janos Follath 0:9a918c8d34dc 155 ciphertext + nonce_len, ciphertext_len - nonce_len - tag_len,
Janos Follath 0:9a918c8d34dc 156 decrypted, &decrypted_len,
Janos Follath 0:9a918c8d34dc 157 ciphertext + ciphertext_len - tag_len, tag_len );
Janos Follath 0:9a918c8d34dc 158 /* Checking the return code is CRITICAL for security here */
Janos Follath 0:9a918c8d34dc 159 if (ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED) {
Janos Follath 0:9a918c8d34dc 160 mbedtls_printf("Something bad is happening! Data is not authentic!\r\n");
Janos Follath 0:9a918c8d34dc 161 return 1;
Janos Follath 0:9a918c8d34dc 162 }
Janos Follath 0:9a918c8d34dc 163 if (ret != 0) {
Janos Follath 0:9a918c8d34dc 164 mbedtls_printf("mbedtls_cipher_authdecrypt() returned -0x%04X\r\n", -ret);
Janos Follath 0:9a918c8d34dc 165 return 1;
Janos Follath 0:9a918c8d34dc 166 }
Janos Follath 0:9a918c8d34dc 167
Janos Follath 0:9a918c8d34dc 168 print_hex("decrypted", decrypted, decrypted_len);
Janos Follath 0:9a918c8d34dc 169
Janos Follath 0:9a918c8d34dc 170 mbedtls_printf("\r\nDONE\r\n");
Janos Follath 0:9a918c8d34dc 171
Janos Follath 0:9a918c8d34dc 172 return 0;
Janos Follath 0:9a918c8d34dc 173 }
Janos Follath 0:9a918c8d34dc 174
Janos Follath 0:9a918c8d34dc 175 int main() {
Janos Follath 0:9a918c8d34dc 176 int ret = example();
Janos Follath 0:9a918c8d34dc 177 if (ret != 0) {
Janos Follath 0:9a918c8d34dc 178 mbedtls_printf("Example failed with error %d\r\n", ret);
Janos Follath 0:9a918c8d34dc 179 }
Janos Follath 0:9a918c8d34dc 180 }