Add test case use of mbedtls_ssl_ticket_rotate

Signed-off-by: Glenn Strauss <gstrauss@gluelogic.com>
diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c
index c77119b..36db2e8 100644
--- a/programs/ssl/ssl_server2.c
+++ b/programs/ssl/ssl_server2.c
@@ -119,6 +119,7 @@
 #define DFL_MFL_CODE            MBEDTLS_SSL_MAX_FRAG_LEN_NONE
 #define DFL_TRUNC_HMAC          -1
 #define DFL_TICKETS             MBEDTLS_SSL_SESSION_TICKETS_ENABLED
+#define DFL_TICKET_ROTATE       0
 #define DFL_TICKET_TIMEOUT      86400
 #define DFL_TICKET_AEAD         MBEDTLS_CIPHER_AES_256_GCM
 #define DFL_CACHE_MAX           -1
@@ -286,6 +287,7 @@
 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
 #define USAGE_TICKETS                                       \
     "    tickets=%%d          default: 1 (enabled)\n"       \
+    "    ticket_rotate=%%d    default: 0 (disabled)\n"      \
     "    ticket_timeout=%%d   default: 86400 (one day)\n"   \
     "    ticket_aead=%%s      default: \"AES-256-GCM\"\n"
 #else
@@ -613,6 +615,7 @@
     unsigned char mfl_code;     /* code for maximum fragment length         */
     int trunc_hmac;             /* accept truncated hmac?                   */
     int tickets;                /* enable / disable session tickets         */
+    int ticket_rotate;          /* session ticket rotate (code coverage)    */
     int ticket_timeout;         /* session ticket lifetime                  */
     int ticket_aead;            /* session ticket protection                */
     int cache_max;              /* max number of session cache entries      */
@@ -1542,6 +1545,7 @@
     opt.mfl_code            = DFL_MFL_CODE;
     opt.trunc_hmac          = DFL_TRUNC_HMAC;
     opt.tickets             = DFL_TICKETS;
+    opt.ticket_rotate       = DFL_TICKET_ROTATE;
     opt.ticket_timeout      = DFL_TICKET_TIMEOUT;
     opt.ticket_aead         = DFL_TICKET_AEAD;
     opt.cache_max           = DFL_CACHE_MAX;
@@ -1915,6 +1919,12 @@
             if( opt.tickets < 0 || opt.tickets > 1 )
                 goto usage;
         }
+        else if( strcmp( p, "ticket_rotate" ) == 0 )
+        {
+            opt.ticket_rotate = atoi( q );
+            if( opt.ticket_rotate < 0 || opt.ticket_rotate > 1 )
+                goto usage;
+        }
         else if( strcmp( p, "ticket_timeout" ) == 0 )
         {
             opt.ticket_timeout = atoi( q );
@@ -2737,6 +2747,24 @@
                 mbedtls_ssl_ticket_write,
                 mbedtls_ssl_ticket_parse,
                 &ticket_ctx );
+
+        /* exercise manual ticket rotation (not required for typical use)
+         * (used for external synchronization of session ticket encryption keys)
+         */
+        if( opt.ticket_rotate ) {
+            #define MAX_KEY_BYTES 32    /* 256 bits *//* library/ssl_ticket.c */
+            unsigned char kbuf[MAX_KEY_BYTES];
+            unsigned char name[4]; /* match mbedtls_ssl_ticket_key name[4] */
+            if( ( ret = rng_get( &rng, name, sizeof( name ) ) ) != 0 ||
+                ( ret = rng_get( &rng, kbuf, sizeof( kbuf ) ) ) != 0 ||
+                ( ret = mbedtls_ssl_ticket_rotate( &ticket_ctx,
+                        name, sizeof(name), kbuf, sizeof(kbuf),
+                        opt.ticket_timeout ) ) != 0 )
+            {
+                mbedtls_printf( " failed\n  ! mbedtls_ssl_ticket_rotate returned %d\n\n", ret );
+                goto exit;
+            }
+        }
     }
 #endif