Skip to content

Commit fb71ca2

Browse files
Andres Amaya GarciaAndres Amaya Garcia
authored andcommitted
Refactor authcrypt
The example is refactored to use C++ classes and allocate the bulk of the mbed TLS context structures in the heap instead of stack.
1 parent 2f2e76a commit fb71ca2

File tree

1 file changed

+154
-126
lines changed

1 file changed

+154
-126
lines changed

authcrypt/main.cpp

Lines changed: 154 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -30,20 +30,6 @@
3030

3131
#include <string.h>
3232

33-
#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
34-
#include "mbedtls/memory_buffer_alloc.h"
35-
#endif
36-
37-
static void print_hex(const char *title, const unsigned char buf[], size_t len)
38-
{
39-
mbedtls_printf("%s: ", title);
40-
41-
for (size_t i = 0; i < len; i++)
42-
mbedtls_printf("%02x", buf[i]);
43-
44-
mbedtls_printf("\r\n");
45-
}
46-
4733
/*
4834
* The pre-shared key. Should be generated randomly and be unique to the
4935
* device/channel/etc. Just used a fixed on here for simplicity.
@@ -53,132 +39,174 @@ static const unsigned char secret_key[16] = {
5339
0xb9, 0xa0, 0xb8, 0xe9, 0x87, 0xb8, 0xc1, 0x72,
5440
};
5541

56-
static int example(void)
57-
{
58-
/* message that should be protected */
59-
const char message[] = "Some things are better left unread";
60-
/* metadata transmitted in the clear but authenticated */
61-
const char metadata[] = "eg sequence number, routing info";
62-
/* ciphertext buffer large enough to hold message + nonce + tag */
63-
unsigned char ciphertext[128] = { 0 };
64-
int ret;
65-
66-
mbedtls_printf("\r\n\r\n");
67-
print_hex("plaintext message", (unsigned char *) message, sizeof message);
68-
69-
/*
70-
* Setup random number generator
71-
* (Note: later this might be done automatically.)
72-
*/
73-
mbedtls_entropy_context entropy; /* entropy pool for seeding PRNG */
74-
mbedtls_ctr_drbg_context drbg; /* pseudo-random generator */
75-
76-
mbedtls_entropy_init(&entropy);
77-
mbedtls_ctr_drbg_init(&drbg);
78-
79-
/* Seed the PRNG using the entropy pool, and throw in our secret key as an
80-
* additional source of randomness. */
81-
ret = mbedtls_ctr_drbg_seed(&drbg, mbedtls_entropy_func, &entropy,
82-
secret_key, sizeof secret_key);
83-
if (ret != 0) {
84-
return 1;
42+
/* Message that should be protected */
43+
static const char message[] = "Some things are better left unread";
44+
/* Metadata transmitted in the clear but authenticated */
45+
static const char metadata[] = "eg sequence number, routing info";
46+
47+
class Authcrypt {
48+
public:
49+
Authcrypt() : ciphertext(), decrypted()
50+
{
51+
mbedtls_entropy_init(&entropy);
52+
mbedtls_ctr_drbg_init(&drbg);
53+
mbedtls_cipher_init(&cipher);
8554
}
8655

87-
/*
88-
* Setup AES-CCM contex
89-
*/
90-
mbedtls_cipher_context_t ctx;
91-
92-
mbedtls_cipher_init(&ctx);
56+
~Authcrypt()
57+
{
58+
memset(ciphertext, 0, sizeof(ciphertext));
59+
memset(decrypted, 0, sizeof(decrypted));
9360

94-
ret = mbedtls_cipher_setup(&ctx, mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_CCM));
95-
if (ret != 0) {
96-
mbedtls_printf("mbedtls_cipher_setup() returned -0x%04X\r\n", -ret);
97-
return 1;
61+
mbedtls_entropy_free(&entropy);
62+
mbedtls_ctr_drbg_free(&drbg);
63+
mbedtls_cipher_free(&cipher);
9864
}
9965

100-
ret = mbedtls_cipher_setkey(&ctx, secret_key, 8 * sizeof secret_key, MBEDTLS_ENCRYPT);
101-
if (ret != 0) {
102-
mbedtls_printf("mbedtls_cipher_setkey() returned -0x%04X\r\n", -ret);
103-
return 1;
66+
int run()
67+
{
68+
mbedtls_printf("\r\n\r\n");
69+
print_hex("plaintext message", (unsigned char *)message,
70+
sizeof(message));
71+
72+
/*
73+
* Seed the PRNG using the entropy pool, and throw in our secret key
74+
* as an additional source of randomness.
75+
*/
76+
int ret = mbedtls_ctr_drbg_seed(&drbg, mbedtls_entropy_func, &entropy,
77+
secret_key, sizeof(secret_key));
78+
if (ret != 0) {
79+
mbedtls_printf("mbedtls_ctr_drbg_seed() returned -0x%04X\r\n",
80+
-ret);
81+
return 1;
82+
}
83+
84+
/* Setup AES-CCM contex */
85+
ret = mbedtls_cipher_setup(&cipher,
86+
mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_CCM));
87+
if (ret != 0) {
88+
mbedtls_printf("mbedtls_cipher_setup() returned -0x%04X\r\n",
89+
-ret);
90+
return 1;
91+
}
92+
93+
ret = mbedtls_cipher_setkey(&cipher, secret_key,
94+
8 * sizeof(secret_key), MBEDTLS_ENCRYPT);
95+
if (ret != 0) {
96+
mbedtls_printf("mbedtls_cipher_setkey() returned -0x%04X\r\n",
97+
-ret);
98+
return 1;
99+
}
100+
101+
/*
102+
* Encrypt-authenticate the message and authenticate additional data
103+
*
104+
* First generate a random 8-byte nonce.
105+
* Put it directly in the output buffer as the recipient will need it.
106+
*
107+
* Warning: you must never re-use the same (key, nonce) pair. One of
108+
* the best ways to ensure this to use a counter for the nonce.
109+
* However, this means you should save the counter accross rebots, if
110+
* the key is a long-term one. The alternative we choose here is to
111+
* generate the nonce randomly. However it only works if you have a
112+
* good source of randomness.
113+
*/
114+
const size_t nonce_len = 8;
115+
mbedtls_ctr_drbg_random(&drbg, ciphertext, nonce_len);
116+
117+
size_t ciphertext_len = 0;
118+
/* Go for a conservative 16-byte (128-bit) tag
119+
* and append it to the ciphertext */
120+
const size_t tag_len = 16;
121+
ret = mbedtls_cipher_auth_encrypt(&cipher, ciphertext, nonce_len,
122+
reinterpret_cast<const unsigned char *>(metadata),
123+
sizeof(metadata),
124+
reinterpret_cast<const unsigned char *>(message),
125+
sizeof(message),
126+
ciphertext + nonce_len, &ciphertext_len,
127+
ciphertext + nonce_len + sizeof(message),
128+
tag_len);
129+
if (ret != 0) {
130+
mbedtls_printf("mbedtls_cipher_auth_encrypt() returned -0x%04X\r\n",
131+
-ret);
132+
return 1;
133+
}
134+
ciphertext_len += nonce_len + tag_len;
135+
136+
/*
137+
* The following information should now be transmitted:
138+
* - First ciphertext_len bytes of ciphertext buffer
139+
* - Metadata if not already transmitted elsewhere
140+
*/
141+
print_hex("ciphertext", ciphertext, ciphertext_len);
142+
143+
/*
144+
* Decrypt-authenticate
145+
*/
146+
size_t decrypted_len = 0;
147+
148+
ret = mbedtls_cipher_setkey(&cipher, secret_key,
149+
8 * sizeof(secret_key), MBEDTLS_DECRYPT);
150+
if (ret != 0) {
151+
mbedtls_printf("mbedtls_cipher_setkey() returned -0x%04X\r\n",
152+
-ret);
153+
return 1;
154+
}
155+
156+
ret = mbedtls_cipher_auth_decrypt(&cipher, ciphertext, nonce_len,
157+
reinterpret_cast<const unsigned char *>(metadata),
158+
sizeof(metadata), ciphertext + nonce_len,
159+
ciphertext_len - nonce_len - tag_len, decrypted,
160+
&decrypted_len, ciphertext + ciphertext_len - tag_len,
161+
tag_len);
162+
/* Checking the return code is CRITICAL for security here */
163+
if (ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED) {
164+
mbedtls_printf("Something bad is happening! Data is not "
165+
"authentic!\r\n");
166+
return 1;
167+
} else if (ret != 0) {
168+
mbedtls_printf("mbedtls_cipher_authdecrypt() returned -0x%04X\r\n",
169+
-ret);
170+
return 1;
171+
}
172+
173+
print_hex("decrypted", decrypted, decrypted_len);
174+
175+
mbedtls_printf("\r\nDONE\r\n");
176+
177+
return 0;
104178
}
105179

106-
/*
107-
* Encrypt-authenticate the message and authenticate additional data
108-
*
109-
* First generate a random 8-byte nonce.
110-
* Put it directly in the output buffer as the recipient will need it.
111-
*
112-
* Warning: you must never re-use the same (key, nonce) pair. One of the
113-
* best ways to ensure this to use a counter for the nonce. However this
114-
* means you should save the counter accross rebots, if the key is a
115-
* long-term one. The alternative we choose here is to generate the nonce
116-
* randomly. However it only works if you have a good source of
117-
* randomness.
118-
*/
119-
const size_t nonce_len = 8;
120-
mbedtls_ctr_drbg_random(&drbg, ciphertext, nonce_len);
121-
122-
size_t ciphertext_len = 0;
123-
/* Go for a conservative 16-byte (128-bit) tag
124-
* and append it to the ciphertext */
125-
const size_t tag_len = 16;
126-
ret = mbedtls_cipher_auth_encrypt(&ctx, ciphertext, nonce_len,
127-
(const unsigned char *) metadata, sizeof metadata,
128-
(const unsigned char *) message, sizeof message,
129-
ciphertext + nonce_len, &ciphertext_len,
130-
ciphertext + nonce_len + sizeof message, tag_len );
131-
if (ret != 0) {
132-
mbedtls_printf("mbedtls_cipher_auth_encrypt() returned -0x%04X\r\n", -ret);
133-
return 1;
134-
}
135-
ciphertext_len += nonce_len + tag_len;
136-
137-
/*
138-
* The following information should now be transmitted:
139-
* - first ciphertext_len bytes of ciphertext buffer
140-
* - metadata if not already transmitted elsewhere
141-
*/
142-
print_hex("ciphertext", ciphertext, ciphertext_len);
143-
144-
/*
145-
* Decrypt-authenticate
146-
*/
147-
unsigned char decrypted[128] = { 0 };
148-
size_t decrypted_len = 0;
149-
150-
ret = mbedtls_cipher_setkey(&ctx, secret_key, 8 * sizeof secret_key, MBEDTLS_DECRYPT);
151-
if (ret != 0) {
152-
mbedtls_printf("mbedtls_cipher_setkey() returned -0x%04X\r\n", -ret);
153-
return 1;
154-
}
180+
private:
181+
void print_hex(const char *title, const unsigned char buf[], size_t len)
182+
{
183+
mbedtls_printf("%s: ", title);
155184

156-
ret = mbedtls_cipher_auth_decrypt(&ctx,
157-
ciphertext, nonce_len,
158-
(const unsigned char *) metadata, sizeof metadata,
159-
ciphertext + nonce_len, ciphertext_len - nonce_len - tag_len,
160-
decrypted, &decrypted_len,
161-
ciphertext + ciphertext_len - tag_len, tag_len );
162-
/* Checking the return code is CRITICAL for security here */
163-
if (ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED) {
164-
mbedtls_printf("Something bad is happening! Data is not authentic!\r\n");
165-
return 1;
166-
}
167-
if (ret != 0) {
168-
mbedtls_printf("mbedtls_cipher_authdecrypt() returned -0x%04X\r\n", -ret);
169-
return 1;
185+
for (size_t i = 0; i < len; i++)
186+
mbedtls_printf("%02x", buf[i]);
187+
188+
mbedtls_printf("\r\n");
170189
}
171190

172-
print_hex("decrypted", decrypted, decrypted_len);
191+
/* Ciphertext buffer large enough to hold message + nonce + tag */
192+
unsigned char ciphertext[128];
193+
unsigned char decrypted[128];
173194

174-
mbedtls_printf("\r\nDONE\r\n");
195+
/* Entropy pool for seeding PRNG */
196+
mbedtls_entropy_context entropy;
175197

176-
return 0;
177-
}
198+
/* Pseudo-random generator */
199+
mbedtls_ctr_drbg_context drbg;
200+
mbedtls_cipher_context_t cipher;
201+
};
178202

179203
int main() {
180-
int ret = example();
181-
if (ret != 0) {
204+
int ret;
205+
Authcrypt *authcrypt = new Authcrypt();
206+
207+
if ((ret = authcrypt->run()) != 0) {
182208
mbedtls_printf("Example failed with error %d\r\n", ret);
183209
}
210+
211+
delete authcrypt;
184212
}

0 commit comments

Comments
 (0)