30
30
31
31
#include < string.h>
32
32
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
-
47
33
/*
48
34
* The pre-shared key. Should be generated randomly and be unique to the
49
35
* device/channel/etc. Just used a fixed on here for simplicity.
@@ -53,132 +39,174 @@ static const unsigned char secret_key[16] = {
53
39
0xb9 , 0xa0 , 0xb8 , 0xe9 , 0x87 , 0xb8 , 0xc1 , 0x72 ,
54
40
};
55
41
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);
85
54
}
86
55
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));
93
60
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);
98
64
}
99
65
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\n DONE\r\n " );
176
+
177
+ return 0 ;
104
178
}
105
179
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);
155
184
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 " );
170
189
}
171
190
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 ];
173
194
174
- mbedtls_printf (" \r\n DONE\r\n " );
195
+ /* Entropy pool for seeding PRNG */
196
+ mbedtls_entropy_context entropy;
175
197
176
- return 0 ;
177
- }
198
+ /* Pseudo-random generator */
199
+ mbedtls_ctr_drbg_context drbg;
200
+ mbedtls_cipher_context_t cipher;
201
+ };
178
202
179
203
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 ) {
182
208
mbedtls_printf (" Example failed with error %d\r\n " , ret);
183
209
}
210
+
211
+ delete authcrypt;
184
212
}
0 commit comments