1 /*
2  *  Benchmark demonstration program
3  *
4  *  Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
5  *  SPDX-License-Identifier: Apache-2.0
6  *
7  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
8  *  not use this file except in compliance with the License.
9  *  You may obtain a copy of the License at
10  *
11  *  http://www.apache.org/licenses/LICENSE-2.0
12  *
13  *  Unless required by applicable law or agreed to in writing, software
14  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  *  See the License for the specific language governing permissions and
17  *  limitations under the License.
18  *
19  *  This file is part of mbed TLS (https://tls.mbed.org)
20  */
21 
22 #if !defined(MBEDTLS_CONFIG_FILE)
23 #include "mbedtls/config.h"
24 #else
25 #include MBEDTLS_CONFIG_FILE
26 #endif
27 
28 #if defined(MBEDTLS_PLATFORM_C)
29 #include "mbedtls/platform.h"
30 #else
31 #include <stdio.h>
32 #define mbedtls_exit       exit
33 #define mbedtls_printf     printf
34 #define mbedtls_snprintf   snprintf
35 #define mbedtls_free       free
36 #endif
37 
38 #if !defined(MBEDTLS_TIMING_C)
main(void)39 int main( void )
40 {
41     mbedtls_printf("MBEDTLS_TIMING_C not defined.\n");
42     return( 0 );
43 }
44 #else
45 
46 #include <string.h>
47 #include <stdlib.h>
48 
49 #include "mbedtls/timing.h"
50 
51 #include "mbedtls/md4.h"
52 #include "mbedtls/md5.h"
53 #include "mbedtls/ripemd160.h"
54 #include "mbedtls/sha1.h"
55 #include "mbedtls/sha256.h"
56 #include "mbedtls/sha512.h"
57 #include "mbedtls/arc4.h"
58 #include "mbedtls/des.h"
59 #include "mbedtls/aes.h"
60 #include "mbedtls/blowfish.h"
61 #include "mbedtls/camellia.h"
62 #include "mbedtls/gcm.h"
63 #include "mbedtls/ccm.h"
64 #include "mbedtls/cmac.h"
65 #include "mbedtls/havege.h"
66 #include "mbedtls/ctr_drbg.h"
67 #include "mbedtls/hmac_drbg.h"
68 #include "mbedtls/rsa.h"
69 #include "mbedtls/dhm.h"
70 #include "mbedtls/ecdsa.h"
71 #include "mbedtls/ecdh.h"
72 #include "mbedtls/error.h"
73 
74 #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
75 #include "mbedtls/memory_buffer_alloc.h"
76 #endif
77 
78 /*
79  * For heap usage estimates, we need an estimate of the overhead per allocated
80  * block. ptmalloc2/3 (used in gnu libc for instance) uses 2 size_t per block,
81  * so use that as our baseline.
82  */
83 #define MEM_BLOCK_OVERHEAD  ( 2 * sizeof( size_t ) )
84 
85 /*
86  * Size to use for the alloc buffer if MEMORY_BUFFER_ALLOC_C is defined.
87  */
88 #define HEAP_SIZE       (1u << 16)  // 64k
89 
90 #define BUFSIZE         1024
91 #define HEADER_FORMAT   "  %-24s :  "
92 #define TITLE_LEN       25
93 
94 #define OPTIONS                                                         \
95     "md4, md5, ripemd160, sha1, sha256, sha512,\n"                      \
96     "arc4, des3, des, camellia, blowfish,\n"                            \
97     "aes_cbc, aes_gcm, aes_ccm, aes_cmac, des3_cmac,\n"                 \
98     "havege, ctr_drbg, hmac_drbg\n"                                     \
99     "rsa, dhm, ecdsa, ecdh.\n"
100 
101 #if defined(MBEDTLS_ERROR_C)
102 #define PRINT_ERROR                                                     \
103         mbedtls_strerror( ret, ( char * )tmp, sizeof( tmp ) );          \
104         mbedtls_printf( "FAILED: %s\n", tmp );
105 #else
106 #define PRINT_ERROR                                                     \
107         mbedtls_printf( "FAILED: -0x%04x\n", -ret );
108 #endif
109 
110 #define TIME_AND_TSC( TITLE, CODE )                                     \
111 do {                                                                    \
112     unsigned long ii, jj, tsc;                                          \
113                                                                         \
114     mbedtls_printf( HEADER_FORMAT, TITLE );                             \
115     fflush( stdout );                                                   \
116                                                                         \
117     mbedtls_set_alarm( 1 );                                             \
118     for( ii = 1; ! mbedtls_timing_alarmed; ii++ )                       \
119     {                                                                   \
120         CODE;                                                           \
121     }                                                                   \
122                                                                         \
123     tsc = mbedtls_timing_hardclock();                                   \
124     for( jj = 0; jj < 1024; jj++ )                                      \
125     {                                                                   \
126         CODE;                                                           \
127     }                                                                   \
128                                                                         \
129     mbedtls_printf( "%9lu Kb/s,  %9lu cycles/byte\n",                   \
130                      ii * BUFSIZE / 1024,                               \
131                      ( mbedtls_timing_hardclock() - tsc ) / ( jj * BUFSIZE ) );         \
132 } while( 0 )
133 
134 #if defined(MBEDTLS_ERROR_C)
135 #define PRINT_ERROR                                                     \
136         mbedtls_strerror( ret, ( char * )tmp, sizeof( tmp ) );          \
137         mbedtls_printf( "FAILED: %s\n", tmp );
138 #else
139 #define PRINT_ERROR                                                     \
140         mbedtls_printf( "FAILED: -0x%04x\n", -ret );
141 #endif
142 
143 #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && defined(MBEDTLS_MEMORY_DEBUG)
144 
145 #define MEMORY_MEASURE_INIT                                             \
146     size_t max_used, max_blocks, max_bytes;                             \
147     size_t prv_used, prv_blocks;                                        \
148     mbedtls_memory_buffer_alloc_cur_get( &prv_used, &prv_blocks );      \
149     mbedtls_memory_buffer_alloc_max_reset( );
150 
151 #define MEMORY_MEASURE_PRINT( title_len )                               \
152     mbedtls_memory_buffer_alloc_max_get( &max_used, &max_blocks );      \
153     for( ii = 12 - title_len; ii != 0; ii-- ) mbedtls_printf( " " );    \
154     max_used -= prv_used;                                               \
155     max_blocks -= prv_blocks;                                           \
156     max_bytes = max_used + MEM_BLOCK_OVERHEAD * max_blocks;             \
157     mbedtls_printf( "%6u heap bytes", (unsigned) max_bytes );
158 
159 #else
160 #define MEMORY_MEASURE_INIT
161 #define MEMORY_MEASURE_PRINT( title_len )
162 #endif
163 
164 #define TIME_PUBLIC( TITLE, TYPE, CODE )                                \
165 do {                                                                    \
166     unsigned long ii;                                                   \
167     int ret;                                                            \
168     MEMORY_MEASURE_INIT;                                                \
169                                                                         \
170     mbedtls_printf( HEADER_FORMAT, TITLE );                             \
171     fflush( stdout );                                                   \
172     mbedtls_set_alarm( 3 );                                             \
173                                                                         \
174     ret = 0;                                                            \
175     for( ii = 1; ! mbedtls_timing_alarmed && ! ret ; ii++ )             \
176     {                                                                   \
177         CODE;                                                           \
178     }                                                                   \
179                                                                         \
180     if( ret != 0 )                                                      \
181     {                                                                   \
182         PRINT_ERROR;                                                    \
183     }                                                                   \
184     else                                                                \
185     {                                                                   \
186         mbedtls_printf( "%6lu " TYPE "/s", ii / 3 );                    \
187         MEMORY_MEASURE_PRINT( sizeof( TYPE ) + 1 );                     \
188         mbedtls_printf( "\n" );                                         \
189     }                                                                   \
190 } while( 0 )
191 
myrand(void * rng_state,unsigned char * output,size_t len)192 static int myrand( void *rng_state, unsigned char *output, size_t len )
193 {
194     size_t use_len;
195     int rnd;
196 
197     if( rng_state != NULL )
198         rng_state  = NULL;
199 
200     while( len > 0 )
201     {
202         use_len = len;
203         if( use_len > sizeof(int) )
204             use_len = sizeof(int);
205 
206         rnd = rand();
207         memcpy( output, &rnd, use_len );
208         output += use_len;
209         len -= use_len;
210     }
211 
212     return( 0 );
213 }
214 
215 /*
216  * Clear some memory that was used to prepare the context
217  */
218 #if defined(MBEDTLS_ECP_C)
ecp_clear_precomputed(mbedtls_ecp_group * grp)219 void ecp_clear_precomputed( mbedtls_ecp_group *grp )
220 {
221     if( grp->T != NULL )
222     {
223         size_t i;
224         for( i = 0; i < grp->T_size; i++ )
225             mbedtls_ecp_point_free( &grp->T[i] );
226         mbedtls_free( grp->T );
227     }
228     grp->T = NULL;
229     grp->T_size = 0;
230 }
231 #else
232 #define ecp_clear_precomputed( g )
233 #endif
234 
235 unsigned char buf[BUFSIZE];
236 
237 typedef struct {
238     char md4, md5, ripemd160, sha1, sha256, sha512,
239          arc4, des3, des,
240          aes_cbc, aes_gcm, aes_ccm, aes_cmac, des3_cmac,
241          camellia, blowfish,
242          havege, ctr_drbg, hmac_drbg,
243          rsa, dhm, ecdsa, ecdh;
244 } todo_list;
245 
main(int argc,char * argv[])246 int main( int argc, char *argv[] )
247 {
248     int i;
249     unsigned char tmp[200];
250     char title[TITLE_LEN];
251     todo_list todo;
252 #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
253     unsigned char alloc_buf[HEAP_SIZE] = { 0 };
254 #endif
255 
256     if( argc <= 1 )
257     {
258         memset( &todo, 1, sizeof( todo ) );
259     }
260     else
261     {
262         memset( &todo, 0, sizeof( todo ) );
263 
264         for( i = 1; i < argc; i++ )
265         {
266             if( strcmp( argv[i], "md4" ) == 0 )
267                 todo.md4 = 1;
268             else if( strcmp( argv[i], "md5" ) == 0 )
269                 todo.md5 = 1;
270             else if( strcmp( argv[i], "ripemd160" ) == 0 )
271                 todo.ripemd160 = 1;
272             else if( strcmp( argv[i], "sha1" ) == 0 )
273                 todo.sha1 = 1;
274             else if( strcmp( argv[i], "sha256" ) == 0 )
275                 todo.sha256 = 1;
276             else if( strcmp( argv[i], "sha512" ) == 0 )
277                 todo.sha512 = 1;
278             else if( strcmp( argv[i], "arc4" ) == 0 )
279                 todo.arc4 = 1;
280             else if( strcmp( argv[i], "des3" ) == 0 )
281                 todo.des3 = 1;
282             else if( strcmp( argv[i], "des" ) == 0 )
283                 todo.des = 1;
284             else if( strcmp( argv[i], "aes_cbc" ) == 0 )
285                 todo.aes_cbc = 1;
286             else if( strcmp( argv[i], "aes_gcm" ) == 0 )
287                 todo.aes_gcm = 1;
288             else if( strcmp( argv[i], "aes_ccm" ) == 0 )
289                 todo.aes_ccm = 1;
290             else if( strcmp( argv[i], "aes_cmac" ) == 0 )
291                 todo.aes_cmac = 1;
292             else if( strcmp( argv[i], "des3_cmac" ) == 0 )
293                 todo.des3_cmac = 1;
294             else if( strcmp( argv[i], "camellia" ) == 0 )
295                 todo.camellia = 1;
296             else if( strcmp( argv[i], "blowfish" ) == 0 )
297                 todo.blowfish = 1;
298             else if( strcmp( argv[i], "havege" ) == 0 )
299                 todo.havege = 1;
300             else if( strcmp( argv[i], "ctr_drbg" ) == 0 )
301                 todo.ctr_drbg = 1;
302             else if( strcmp( argv[i], "hmac_drbg" ) == 0 )
303                 todo.hmac_drbg = 1;
304             else if( strcmp( argv[i], "rsa" ) == 0 )
305                 todo.rsa = 1;
306             else if( strcmp( argv[i], "dhm" ) == 0 )
307                 todo.dhm = 1;
308             else if( strcmp( argv[i], "ecdsa" ) == 0 )
309                 todo.ecdsa = 1;
310             else if( strcmp( argv[i], "ecdh" ) == 0 )
311                 todo.ecdh = 1;
312             else
313             {
314                 mbedtls_printf( "Unrecognized option: %s\n", argv[i] );
315                 mbedtls_printf( "Available options: " OPTIONS );
316             }
317         }
318     }
319 
320     mbedtls_printf( "\n" );
321 
322 #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
323     mbedtls_memory_buffer_alloc_init( alloc_buf, sizeof( alloc_buf ) );
324 #endif
325     memset( buf, 0xAA, sizeof( buf ) );
326     memset( tmp, 0xBB, sizeof( tmp ) );
327 
328 #if defined(MBEDTLS_MD4_C)
329     if( todo.md4 )
330         TIME_AND_TSC( "MD4", mbedtls_md4( buf, BUFSIZE, tmp ) );
331 #endif
332 
333 #if defined(MBEDTLS_MD5_C)
334     if( todo.md5 )
335         TIME_AND_TSC( "MD5", mbedtls_md5( buf, BUFSIZE, tmp ) );
336 #endif
337 
338 #if defined(MBEDTLS_RIPEMD160_C)
339     if( todo.ripemd160 )
340         TIME_AND_TSC( "RIPEMD160", mbedtls_ripemd160( buf, BUFSIZE, tmp ) );
341 #endif
342 
343 #if defined(MBEDTLS_SHA1_C)
344     if( todo.sha1 )
345         TIME_AND_TSC( "SHA-1", mbedtls_sha1( buf, BUFSIZE, tmp ) );
346 #endif
347 
348 #if defined(MBEDTLS_SHA256_C)
349     if( todo.sha256 )
350         TIME_AND_TSC( "SHA-256", mbedtls_sha256( buf, BUFSIZE, tmp, 0 ) );
351 #endif
352 
353 #if defined(MBEDTLS_SHA512_C)
354     if( todo.sha512 )
355         TIME_AND_TSC( "SHA-512", mbedtls_sha512( buf, BUFSIZE, tmp, 0 ) );
356 #endif
357 
358 #if defined(MBEDTLS_ARC4_C)
359     if( todo.arc4 )
360     {
361         mbedtls_arc4_context arc4;
362         mbedtls_arc4_init( &arc4 );
363         mbedtls_arc4_setup( &arc4, tmp, 32 );
364         TIME_AND_TSC( "ARC4", mbedtls_arc4_crypt( &arc4, BUFSIZE, buf, buf ) );
365         mbedtls_arc4_free( &arc4 );
366     }
367 #endif
368 
369 #if defined(MBEDTLS_DES_C)
370 #if defined(MBEDTLS_CIPHER_MODE_CBC)
371     if( todo.des3 )
372     {
373         mbedtls_des3_context des3;
374         mbedtls_des3_init( &des3 );
375         mbedtls_des3_set3key_enc( &des3, tmp );
376         TIME_AND_TSC( "3DES",
377                 mbedtls_des3_crypt_cbc( &des3, MBEDTLS_DES_ENCRYPT, BUFSIZE, tmp, buf, buf ) );
378         mbedtls_des3_free( &des3 );
379     }
380 
381     if( todo.des )
382     {
383         mbedtls_des_context des;
384         mbedtls_des_init( &des );
385         mbedtls_des_setkey_enc( &des, tmp );
386         TIME_AND_TSC( "DES",
387                 mbedtls_des_crypt_cbc( &des, MBEDTLS_DES_ENCRYPT, BUFSIZE, tmp, buf, buf ) );
388         mbedtls_des_free( &des );
389     }
390 
391 #endif /* MBEDTLS_CIPHER_MODE_CBC */
392 #if defined(MBEDTLS_CMAC_C)
393     if( todo.des3_cmac )
394     {
395         unsigned char output[8];
396         const mbedtls_cipher_info_t *cipher_info;
397 
398         memset( buf, 0, sizeof( buf ) );
399         memset( tmp, 0, sizeof( tmp ) );
400 
401         cipher_info = mbedtls_cipher_info_from_type( MBEDTLS_CIPHER_DES_EDE3_ECB );
402 
403         TIME_AND_TSC( "3DES-CMAC",
404                       mbedtls_cipher_cmac( cipher_info, tmp, 192, buf,
405                       BUFSIZE, output ) );
406     }
407 #endif /* MBEDTLS_CMAC_C */
408 #endif /* MBEDTLS_DES_C */
409 
410 #if defined(MBEDTLS_AES_C)
411 #if defined(MBEDTLS_CIPHER_MODE_CBC)
412     if( todo.aes_cbc )
413     {
414         int keysize;
415         mbedtls_aes_context aes;
416         mbedtls_aes_init( &aes );
417         for( keysize = 128; keysize <= 256; keysize += 64 )
418         {
419             mbedtls_snprintf( title, sizeof( title ), "AES-CBC-%d", keysize );
420 
421             memset( buf, 0, sizeof( buf ) );
422             memset( tmp, 0, sizeof( tmp ) );
423             mbedtls_aes_setkey_enc( &aes, tmp, keysize );
424 
425             TIME_AND_TSC( title,
426                 mbedtls_aes_crypt_cbc( &aes, MBEDTLS_AES_ENCRYPT, BUFSIZE, tmp, buf, buf ) );
427         }
428         mbedtls_aes_free( &aes );
429     }
430 #endif
431 #if defined(MBEDTLS_GCM_C)
432     if( todo.aes_gcm )
433     {
434         int keysize;
435         mbedtls_gcm_context gcm;
436 
437         mbedtls_gcm_init( &gcm );
438         for( keysize = 128; keysize <= 256; keysize += 64 )
439         {
440             mbedtls_snprintf( title, sizeof( title ), "AES-GCM-%d", keysize );
441 
442             memset( buf, 0, sizeof( buf ) );
443             memset( tmp, 0, sizeof( tmp ) );
444             mbedtls_gcm_setkey( &gcm, MBEDTLS_CIPHER_ID_AES, tmp, keysize );
445 
446             TIME_AND_TSC( title,
447                     mbedtls_gcm_crypt_and_tag( &gcm, MBEDTLS_GCM_ENCRYPT, BUFSIZE, tmp,
448                         12, NULL, 0, buf, buf, 16, tmp ) );
449 
450             mbedtls_gcm_free( &gcm );
451         }
452     }
453 #endif
454 #if defined(MBEDTLS_CCM_C)
455     if( todo.aes_ccm )
456     {
457         int keysize;
458         mbedtls_ccm_context ccm;
459 
460         mbedtls_ccm_init( &ccm );
461         for( keysize = 128; keysize <= 256; keysize += 64 )
462         {
463             mbedtls_snprintf( title, sizeof( title ), "AES-CCM-%d", keysize );
464 
465             memset( buf, 0, sizeof( buf ) );
466             memset( tmp, 0, sizeof( tmp ) );
467             mbedtls_ccm_setkey( &ccm, MBEDTLS_CIPHER_ID_AES, tmp, keysize );
468 
469             TIME_AND_TSC( title,
470                     mbedtls_ccm_encrypt_and_tag( &ccm, BUFSIZE, tmp,
471                         12, NULL, 0, buf, buf, tmp, 16 ) );
472 
473             mbedtls_ccm_free( &ccm );
474         }
475     }
476 #endif
477 #if defined(MBEDTLS_CMAC_C)
478     if( todo.aes_cmac )
479     {
480         unsigned char output[16];
481         const mbedtls_cipher_info_t *cipher_info;
482         mbedtls_cipher_type_t cipher_type;
483         int keysize;
484 
485         for( keysize = 128, cipher_type = MBEDTLS_CIPHER_AES_128_ECB;
486              keysize <= 256;
487              keysize += 64, cipher_type++ )
488         {
489             mbedtls_snprintf( title, sizeof( title ), "AES-CMAC-%d", keysize );
490 
491             memset( buf, 0, sizeof( buf ) );
492             memset( tmp, 0, sizeof( tmp ) );
493 
494             cipher_info = mbedtls_cipher_info_from_type( cipher_type );
495 
496             TIME_AND_TSC( title,
497                           mbedtls_cipher_cmac( cipher_info, tmp, keysize,
498                                                buf, BUFSIZE, output ) );
499         }
500 
501         memset( buf, 0, sizeof( buf ) );
502         memset( tmp, 0, sizeof( tmp ) );
503         TIME_AND_TSC( "AES-CMAC-PRF-128",
504                       mbedtls_aes_cmac_prf_128( tmp, 16, buf, BUFSIZE,
505                                                 output ) );
506     }
507 #endif /* MBEDTLS_CMAC_C */
508 #endif /* MBEDTLS_AES_C */
509 
510 #if defined(MBEDTLS_CAMELLIA_C) && defined(MBEDTLS_CIPHER_MODE_CBC)
511     if( todo.camellia )
512     {
513         int keysize;
514         mbedtls_camellia_context camellia;
515         mbedtls_camellia_init( &camellia );
516         for( keysize = 128; keysize <= 256; keysize += 64 )
517         {
518             mbedtls_snprintf( title, sizeof( title ), "CAMELLIA-CBC-%d", keysize );
519 
520             memset( buf, 0, sizeof( buf ) );
521             memset( tmp, 0, sizeof( tmp ) );
522             mbedtls_camellia_setkey_enc( &camellia, tmp, keysize );
523 
524             TIME_AND_TSC( title,
525                     mbedtls_camellia_crypt_cbc( &camellia, MBEDTLS_CAMELLIA_ENCRYPT,
526                         BUFSIZE, tmp, buf, buf ) );
527         }
528         mbedtls_camellia_free( &camellia );
529     }
530 #endif
531 
532 #if defined(MBEDTLS_BLOWFISH_C) && defined(MBEDTLS_CIPHER_MODE_CBC)
533     if( todo.blowfish )
534     {
535         int keysize;
536         mbedtls_blowfish_context blowfish;
537         mbedtls_blowfish_init( &blowfish );
538 
539         for( keysize = 128; keysize <= 256; keysize += 64 )
540         {
541             mbedtls_snprintf( title, sizeof( title ), "BLOWFISH-CBC-%d", keysize );
542 
543             memset( buf, 0, sizeof( buf ) );
544             memset( tmp, 0, sizeof( tmp ) );
545             mbedtls_blowfish_setkey( &blowfish, tmp, keysize );
546 
547             TIME_AND_TSC( title,
548                     mbedtls_blowfish_crypt_cbc( &blowfish, MBEDTLS_BLOWFISH_ENCRYPT, BUFSIZE,
549                         tmp, buf, buf ) );
550         }
551 
552         mbedtls_blowfish_free( &blowfish );
553     }
554 #endif
555 
556 #if defined(MBEDTLS_HAVEGE_C)
557     if( todo.havege )
558     {
559         mbedtls_havege_state hs;
560         mbedtls_havege_init( &hs );
561         TIME_AND_TSC( "HAVEGE", mbedtls_havege_random( &hs, buf, BUFSIZE ) );
562         mbedtls_havege_free( &hs );
563     }
564 #endif
565 
566 #if defined(MBEDTLS_CTR_DRBG_C)
567     if( todo.ctr_drbg )
568     {
569         mbedtls_ctr_drbg_context ctr_drbg;
570 
571         mbedtls_ctr_drbg_init( &ctr_drbg );
572 
573         if( mbedtls_ctr_drbg_seed( &ctr_drbg, myrand, NULL, NULL, 0 ) != 0 )
574             mbedtls_exit(1);
575         TIME_AND_TSC( "CTR_DRBG (NOPR)",
576                 if( mbedtls_ctr_drbg_random( &ctr_drbg, buf, BUFSIZE ) != 0 )
577                 mbedtls_exit(1) );
578 
579         if( mbedtls_ctr_drbg_seed( &ctr_drbg, myrand, NULL, NULL, 0 ) != 0 )
580             mbedtls_exit(1);
581         mbedtls_ctr_drbg_set_prediction_resistance( &ctr_drbg, MBEDTLS_CTR_DRBG_PR_ON );
582         TIME_AND_TSC( "CTR_DRBG (PR)",
583                 if( mbedtls_ctr_drbg_random( &ctr_drbg, buf, BUFSIZE ) != 0 )
584                 mbedtls_exit(1) );
585         mbedtls_ctr_drbg_free( &ctr_drbg );
586     }
587 #endif
588 
589 #if defined(MBEDTLS_HMAC_DRBG_C)
590     if( todo.hmac_drbg )
591     {
592         mbedtls_hmac_drbg_context hmac_drbg;
593         const mbedtls_md_info_t *md_info;
594 
595         mbedtls_hmac_drbg_init( &hmac_drbg );
596 
597 #if defined(MBEDTLS_SHA1_C)
598         if( ( md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ) ) == NULL )
599             mbedtls_exit(1);
600 
601         if( mbedtls_hmac_drbg_seed( &hmac_drbg, md_info, myrand, NULL, NULL, 0 ) != 0 )
602             mbedtls_exit(1);
603         TIME_AND_TSC( "HMAC_DRBG SHA-1 (NOPR)",
604                 if( mbedtls_hmac_drbg_random( &hmac_drbg, buf, BUFSIZE ) != 0 )
605                 mbedtls_exit(1) );
606         mbedtls_hmac_drbg_free( &hmac_drbg );
607 
608         if( mbedtls_hmac_drbg_seed( &hmac_drbg, md_info, myrand, NULL, NULL, 0 ) != 0 )
609             mbedtls_exit(1);
610         mbedtls_hmac_drbg_set_prediction_resistance( &hmac_drbg,
611                                              MBEDTLS_HMAC_DRBG_PR_ON );
612         TIME_AND_TSC( "HMAC_DRBG SHA-1 (PR)",
613                 if( mbedtls_hmac_drbg_random( &hmac_drbg, buf, BUFSIZE ) != 0 )
614                 mbedtls_exit(1) );
615         mbedtls_hmac_drbg_free( &hmac_drbg );
616 #endif
617 
618 #if defined(MBEDTLS_SHA256_C)
619         if( ( md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ) ) == NULL )
620             mbedtls_exit(1);
621 
622         if( mbedtls_hmac_drbg_seed( &hmac_drbg, md_info, myrand, NULL, NULL, 0 ) != 0 )
623             mbedtls_exit(1);
624         TIME_AND_TSC( "HMAC_DRBG SHA-256 (NOPR)",
625                 if( mbedtls_hmac_drbg_random( &hmac_drbg, buf, BUFSIZE ) != 0 )
626                 mbedtls_exit(1) );
627         mbedtls_hmac_drbg_free( &hmac_drbg );
628 
629         if( mbedtls_hmac_drbg_seed( &hmac_drbg, md_info, myrand, NULL, NULL, 0 ) != 0 )
630             mbedtls_exit(1);
631         mbedtls_hmac_drbg_set_prediction_resistance( &hmac_drbg,
632                                              MBEDTLS_HMAC_DRBG_PR_ON );
633         TIME_AND_TSC( "HMAC_DRBG SHA-256 (PR)",
634                 if( mbedtls_hmac_drbg_random( &hmac_drbg, buf, BUFSIZE ) != 0 )
635                 mbedtls_exit(1) );
636         mbedtls_hmac_drbg_free( &hmac_drbg );
637 #endif
638     }
639 #endif
640 
641 #if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_GENPRIME)
642     if( todo.rsa )
643     {
644         int keysize;
645         mbedtls_rsa_context rsa;
646         for( keysize = 2048; keysize <= 4096; keysize *= 2 )
647         {
648             mbedtls_snprintf( title, sizeof( title ), "RSA-%d", keysize );
649 
650             mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, 0 );
651             mbedtls_rsa_gen_key( &rsa, myrand, NULL, keysize, 65537 );
652 
653             TIME_PUBLIC( title, " public",
654                     buf[0] = 0;
655                     ret = mbedtls_rsa_public( &rsa, buf, buf ) );
656 
657             TIME_PUBLIC( title, "private",
658                     buf[0] = 0;
659                     ret = mbedtls_rsa_private( &rsa, myrand, NULL, buf, buf ) );
660 
661             mbedtls_rsa_free( &rsa );
662         }
663     }
664 #endif
665 
666 #if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_BIGNUM_C)
667     if( todo.dhm )
668     {
669         int dhm_sizes[] = { 2048, 3072 };
670         const char *dhm_P[] = {
671             MBEDTLS_DHM_RFC3526_MODP_2048_P,
672             MBEDTLS_DHM_RFC3526_MODP_3072_P,
673         };
674         const char *dhm_G[] = {
675             MBEDTLS_DHM_RFC3526_MODP_2048_G,
676             MBEDTLS_DHM_RFC3526_MODP_3072_G,
677         };
678 
679         mbedtls_dhm_context dhm;
680         size_t olen;
681         for( i = 0; (size_t) i < sizeof( dhm_sizes ) / sizeof( dhm_sizes[0] ); i++ )
682         {
683             mbedtls_dhm_init( &dhm );
684 
685             if( mbedtls_mpi_read_string( &dhm.P, 16, dhm_P[i] ) != 0 ||
686                 mbedtls_mpi_read_string( &dhm.G, 16, dhm_G[i] ) != 0 )
687             {
688                 mbedtls_exit( 1 );
689             }
690 
691             dhm.len = mbedtls_mpi_size( &dhm.P );
692             mbedtls_dhm_make_public( &dhm, (int) dhm.len, buf, dhm.len, myrand, NULL );
693             if( mbedtls_mpi_copy( &dhm.GY, &dhm.GX ) != 0 )
694                 mbedtls_exit( 1 );
695 
696             mbedtls_snprintf( title, sizeof( title ), "DHE-%d", dhm_sizes[i] );
697             TIME_PUBLIC( title, "handshake",
698                     ret |= mbedtls_dhm_make_public( &dhm, (int) dhm.len, buf, dhm.len,
699                                             myrand, NULL );
700                     ret |= mbedtls_dhm_calc_secret( &dhm, buf, sizeof( buf ), &olen, myrand, NULL ) );
701 
702             mbedtls_snprintf( title, sizeof( title ), "DH-%d", dhm_sizes[i] );
703             TIME_PUBLIC( title, "handshake",
704                     ret |= mbedtls_dhm_calc_secret( &dhm, buf, sizeof( buf ), &olen, myrand, NULL ) );
705 
706             mbedtls_dhm_free( &dhm );
707         }
708     }
709 #endif
710 
711 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_SHA256_C)
712     if( todo.ecdsa )
713     {
714         mbedtls_ecdsa_context ecdsa;
715         const mbedtls_ecp_curve_info *curve_info;
716         size_t sig_len;
717 
718         memset( buf, 0x2A, sizeof( buf ) );
719 
720         for( curve_info = mbedtls_ecp_curve_list();
721              curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
722              curve_info++ )
723         {
724             mbedtls_ecdsa_init( &ecdsa );
725 
726             if( mbedtls_ecdsa_genkey( &ecdsa, curve_info->grp_id, myrand, NULL ) != 0 )
727                 mbedtls_exit( 1 );
728             ecp_clear_precomputed( &ecdsa.grp );
729 
730             mbedtls_snprintf( title, sizeof( title ), "ECDSA-%s",
731                                               curve_info->name );
732             TIME_PUBLIC( title, "sign",
733                     ret = mbedtls_ecdsa_write_signature( &ecdsa, MBEDTLS_MD_SHA256, buf, curve_info->bit_size,
734                                                 tmp, &sig_len, myrand, NULL ) );
735 
736             mbedtls_ecdsa_free( &ecdsa );
737         }
738 
739         for( curve_info = mbedtls_ecp_curve_list();
740              curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
741              curve_info++ )
742         {
743             mbedtls_ecdsa_init( &ecdsa );
744 
745             if( mbedtls_ecdsa_genkey( &ecdsa, curve_info->grp_id, myrand, NULL ) != 0 ||
746                 mbedtls_ecdsa_write_signature( &ecdsa, MBEDTLS_MD_SHA256, buf, curve_info->bit_size,
747                                                tmp, &sig_len, myrand, NULL ) != 0 )
748             {
749                 mbedtls_exit( 1 );
750             }
751             ecp_clear_precomputed( &ecdsa.grp );
752 
753             mbedtls_snprintf( title, sizeof( title ), "ECDSA-%s",
754                                               curve_info->name );
755             TIME_PUBLIC( title, "verify",
756                     ret = mbedtls_ecdsa_read_signature( &ecdsa, buf, curve_info->bit_size,
757                                                 tmp, sig_len ) );
758 
759             mbedtls_ecdsa_free( &ecdsa );
760         }
761     }
762 #endif
763 
764 #if defined(MBEDTLS_ECDH_C)
765     if( todo.ecdh )
766     {
767         mbedtls_ecdh_context ecdh;
768 #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
769         mbedtls_mpi z;
770 #endif
771         const mbedtls_ecp_curve_info *curve_info;
772         size_t olen;
773 
774         for( curve_info = mbedtls_ecp_curve_list();
775              curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
776              curve_info++ )
777         {
778             mbedtls_ecdh_init( &ecdh );
779 
780             if( mbedtls_ecp_group_load( &ecdh.grp, curve_info->grp_id ) != 0 ||
781                 mbedtls_ecdh_make_public( &ecdh, &olen, buf, sizeof( buf),
782                                   myrand, NULL ) != 0 ||
783                 mbedtls_ecp_copy( &ecdh.Qp, &ecdh.Q ) != 0 )
784             {
785                 mbedtls_exit( 1 );
786             }
787             ecp_clear_precomputed( &ecdh.grp );
788 
789             mbedtls_snprintf( title, sizeof( title ), "ECDHE-%s",
790                                               curve_info->name );
791             TIME_PUBLIC( title, "handshake",
792                     ret |= mbedtls_ecdh_make_public( &ecdh, &olen, buf, sizeof( buf),
793                                              myrand, NULL );
794                     ret |= mbedtls_ecdh_calc_secret( &ecdh, &olen, buf, sizeof( buf ),
795                                              myrand, NULL ) );
796             mbedtls_ecdh_free( &ecdh );
797         }
798 
799         /* Curve25519 needs to be handled separately */
800 #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
801         mbedtls_ecdh_init( &ecdh );
802         mbedtls_mpi_init( &z );
803 
804         if( mbedtls_ecp_group_load( &ecdh.grp, MBEDTLS_ECP_DP_CURVE25519 ) != 0 ||
805             mbedtls_ecdh_gen_public( &ecdh.grp, &ecdh.d, &ecdh.Qp, myrand, NULL ) != 0 )
806         {
807             mbedtls_exit( 1 );
808         }
809 
810         TIME_PUBLIC(  "ECDHE-Curve25519", "handshake",
811                 ret |= mbedtls_ecdh_gen_public( &ecdh.grp, &ecdh.d, &ecdh.Q,
812                                         myrand, NULL );
813                 ret |= mbedtls_ecdh_compute_shared( &ecdh.grp, &z, &ecdh.Qp, &ecdh.d,
814                                             myrand, NULL ) );
815 
816         mbedtls_ecdh_free( &ecdh );
817         mbedtls_mpi_free( &z );
818 #endif
819 
820         for( curve_info = mbedtls_ecp_curve_list();
821              curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
822              curve_info++ )
823         {
824             mbedtls_ecdh_init( &ecdh );
825 
826             if( mbedtls_ecp_group_load( &ecdh.grp, curve_info->grp_id ) != 0 ||
827                 mbedtls_ecdh_make_public( &ecdh, &olen, buf, sizeof( buf),
828                                   myrand, NULL ) != 0 ||
829                 mbedtls_ecp_copy( &ecdh.Qp, &ecdh.Q ) != 0 ||
830                 mbedtls_ecdh_make_public( &ecdh, &olen, buf, sizeof( buf),
831                                   myrand, NULL ) != 0 )
832             {
833                 mbedtls_exit( 1 );
834             }
835             ecp_clear_precomputed( &ecdh.grp );
836 
837             mbedtls_snprintf( title, sizeof( title ), "ECDH-%s",
838                                               curve_info->name );
839             TIME_PUBLIC( title, "handshake",
840                     ret |= mbedtls_ecdh_calc_secret( &ecdh, &olen, buf, sizeof( buf ),
841                                              myrand, NULL ) );
842             mbedtls_ecdh_free( &ecdh );
843         }
844 
845         /* Curve25519 needs to be handled separately */
846 #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
847         mbedtls_ecdh_init( &ecdh );
848         mbedtls_mpi_init( &z );
849 
850         if( mbedtls_ecp_group_load( &ecdh.grp, MBEDTLS_ECP_DP_CURVE25519 ) != 0 ||
851             mbedtls_ecdh_gen_public( &ecdh.grp, &ecdh.d, &ecdh.Qp,
852                              myrand, NULL ) != 0 ||
853             mbedtls_ecdh_gen_public( &ecdh.grp, &ecdh.d, &ecdh.Q, myrand, NULL ) != 0 )
854         {
855             mbedtls_exit( 1 );
856         }
857 
858         TIME_PUBLIC(  "ECDH-Curve25519", "handshake",
859                 ret |= mbedtls_ecdh_compute_shared( &ecdh.grp, &z, &ecdh.Qp, &ecdh.d,
860                                             myrand, NULL ) );
861 
862         mbedtls_ecdh_free( &ecdh );
863         mbedtls_mpi_free( &z );
864 #endif
865     }
866 #endif
867 
868     mbedtls_printf( "\n" );
869 
870 #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
871     mbedtls_memory_buffer_alloc_free();
872 #endif
873 
874 #if defined(_WIN32)
875     mbedtls_printf( "  Press Enter to exit this program.\n" );
876     fflush( stdout ); getchar();
877 #endif
878 
879     return( 0 );
880 }
881 
882 #endif /* MBEDTLS_TIMING_C */
883