Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  *  TLS server tickets callbacks implementation
  3.  *
  4.  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
  5.  *  SPDX-License-Identifier: GPL-2.0
  6.  *
  7.  *  This program is free software; you can redistribute it and/or modify
  8.  *  it under the terms of the GNU General Public License as published by
  9.  *  the Free Software Foundation; either version 2 of the License, or
  10.  *  (at your option) any later version.
  11.  *
  12.  *  This program is distributed in the hope that it will be useful,
  13.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  *  GNU General Public License for more details.
  16.  *
  17.  *  You should have received a copy of the GNU General Public License along
  18.  *  with this program; if not, write to the Free Software Foundation, Inc.,
  19.  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  20.  *
  21.  *  This file is part of mbed TLS (https://tls.mbed.org)
  22.  */
  23.  
  24. #if !defined(MBEDTLS_CONFIG_FILE)
  25. #include "mbedtls/config.h"
  26. #else
  27. #include MBEDTLS_CONFIG_FILE
  28. #endif
  29.  
  30. #if defined(MBEDTLS_SSL_TICKET_C)
  31.  
  32. #if defined(MBEDTLS_PLATFORM_C)
  33. #include "mbedtls/platform.h"
  34. #else
  35. #include <stdlib.h>
  36. #define mbedtls_calloc    calloc
  37. #define mbedtls_free      free
  38. #endif
  39.  
  40. #include "mbedtls/ssl_ticket.h"
  41. #include "mbedtls/platform_util.h"
  42.  
  43. #include <string.h>
  44.  
  45. /*
  46.  * Initialze context
  47.  */
  48. void mbedtls_ssl_ticket_init( mbedtls_ssl_ticket_context *ctx )
  49. {
  50.     memset( ctx, 0, sizeof( mbedtls_ssl_ticket_context ) );
  51.  
  52. #if defined(MBEDTLS_THREADING_C)
  53.     mbedtls_mutex_init( &ctx->mutex );
  54. #endif
  55. }
  56.  
  57. #define MAX_KEY_BYTES 32    /* 256 bits */
  58.  
  59. /*
  60.  * Generate/update a key
  61.  */
  62. static int ssl_ticket_gen_key( mbedtls_ssl_ticket_context *ctx,
  63.                                unsigned char index )
  64. {
  65.     int ret;
  66.     unsigned char buf[MAX_KEY_BYTES];
  67.     mbedtls_ssl_ticket_key *key = ctx->keys + index;
  68.  
  69. #if defined(MBEDTLS_HAVE_TIME)
  70.     key->generation_time = (uint32_t) mbedtls_time( NULL );
  71. #endif
  72.  
  73.     if( ( ret = ctx->f_rng( ctx->p_rng, key->name, sizeof( key->name ) ) ) != 0 )
  74.         return( ret );
  75.  
  76.     if( ( ret = ctx->f_rng( ctx->p_rng, buf, sizeof( buf ) ) ) != 0 )
  77.         return( ret );
  78.  
  79.     /* With GCM and CCM, same context can encrypt & decrypt */
  80.     ret = mbedtls_cipher_setkey( &key->ctx, buf,
  81.                                  mbedtls_cipher_get_key_bitlen( &key->ctx ),
  82.                                  MBEDTLS_ENCRYPT );
  83.  
  84.     mbedtls_platform_zeroize( buf, sizeof( buf ) );
  85.  
  86.     return( ret );
  87. }
  88.  
  89. /*
  90.  * Rotate/generate keys if necessary
  91.  */
  92. static int ssl_ticket_update_keys( mbedtls_ssl_ticket_context *ctx )
  93. {
  94. #if !defined(MBEDTLS_HAVE_TIME)
  95.     ((void) ctx);
  96. #else
  97.     if( ctx->ticket_lifetime != 0 )
  98.     {
  99.         uint32_t current_time = (uint32_t) mbedtls_time( NULL );
  100.         uint32_t key_time = ctx->keys[ctx->active].generation_time;
  101.  
  102.         if( current_time >= key_time &&
  103.             current_time - key_time < ctx->ticket_lifetime )
  104.         {
  105.             return( 0 );
  106.         }
  107.  
  108.         ctx->active = 1 - ctx->active;
  109.  
  110.         return( ssl_ticket_gen_key( ctx, ctx->active ) );
  111.     }
  112.     else
  113. #endif /* MBEDTLS_HAVE_TIME */
  114.         return( 0 );
  115. }
  116.  
  117. /*
  118.  * Setup context for actual use
  119.  */
  120. int mbedtls_ssl_ticket_setup( mbedtls_ssl_ticket_context *ctx,
  121.     int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
  122.     mbedtls_cipher_type_t cipher,
  123.     uint32_t lifetime )
  124. {
  125.     int ret;
  126.     const mbedtls_cipher_info_t *cipher_info;
  127.  
  128.     ctx->f_rng = f_rng;
  129.     ctx->p_rng = p_rng;
  130.  
  131.     ctx->ticket_lifetime = lifetime;
  132.  
  133.     cipher_info = mbedtls_cipher_info_from_type( cipher);
  134.     if( cipher_info == NULL )
  135.         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
  136.  
  137.     if( cipher_info->mode != MBEDTLS_MODE_GCM &&
  138.         cipher_info->mode != MBEDTLS_MODE_CCM )
  139.     {
  140.         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
  141.     }
  142.  
  143.     if( cipher_info->key_bitlen > 8 * MAX_KEY_BYTES )
  144.         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
  145.  
  146.     if( ( ret = mbedtls_cipher_setup( &ctx->keys[0].ctx, cipher_info ) ) != 0 ||
  147.         ( ret = mbedtls_cipher_setup( &ctx->keys[1].ctx, cipher_info ) ) != 0 )
  148.     {
  149.         return( ret );
  150.     }
  151.  
  152.     if( ( ret = ssl_ticket_gen_key( ctx, 0 ) ) != 0 ||
  153.         ( ret = ssl_ticket_gen_key( ctx, 1 ) ) != 0 )
  154.     {
  155.         return( ret );
  156.     }
  157.  
  158.     return( 0 );
  159. }
  160.  
  161. /*
  162.  * Serialize a session in the following format:
  163.  *  0   .   n-1     session structure, n = sizeof(mbedtls_ssl_session)
  164.  *  n   .   n+2     peer_cert length = m (0 if no certificate)
  165.  *  n+3 .   n+2+m   peer cert ASN.1
  166.  */
  167. static int ssl_save_session( const mbedtls_ssl_session *session,
  168.                              unsigned char *buf, size_t buf_len,
  169.                              size_t *olen )
  170. {
  171.     unsigned char *p = buf;
  172.     size_t left = buf_len;
  173. #if defined(MBEDTLS_X509_CRT_PARSE_C)
  174.     size_t cert_len;
  175. #endif /* MBEDTLS_X509_CRT_PARSE_C */
  176.  
  177.     if( left < sizeof( mbedtls_ssl_session ) )
  178.         return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
  179.  
  180.     memcpy( p, session, sizeof( mbedtls_ssl_session ) );
  181.     p += sizeof( mbedtls_ssl_session );
  182.     left -= sizeof( mbedtls_ssl_session );
  183.  
  184. #if defined(MBEDTLS_X509_CRT_PARSE_C)
  185.     if( session->peer_cert == NULL )
  186.         cert_len = 0;
  187.     else
  188.         cert_len = session->peer_cert->raw.len;
  189.  
  190.     if( left < 3 + cert_len )
  191.         return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
  192.  
  193.     *p++ = (unsigned char)( ( cert_len >> 16 ) & 0xFF );
  194.     *p++ = (unsigned char)( ( cert_len >>  8 ) & 0xFF );
  195.     *p++ = (unsigned char)( ( cert_len       ) & 0xFF );
  196.  
  197.     if( session->peer_cert != NULL )
  198.         memcpy( p, session->peer_cert->raw.p, cert_len );
  199.  
  200.     p += cert_len;
  201. #endif /* MBEDTLS_X509_CRT_PARSE_C */
  202.  
  203.     *olen = p - buf;
  204.  
  205.     return( 0 );
  206. }
  207.  
  208. /*
  209.  * Unserialise session, see ssl_save_session()
  210.  */
  211. static int ssl_load_session( mbedtls_ssl_session *session,
  212.                              const unsigned char *buf, size_t len )
  213. {
  214.     const unsigned char *p = buf;
  215.     const unsigned char * const end = buf + len;
  216. #if defined(MBEDTLS_X509_CRT_PARSE_C)
  217.     size_t cert_len;
  218. #endif /* MBEDTLS_X509_CRT_PARSE_C */
  219.  
  220.     if( sizeof( mbedtls_ssl_session ) > (size_t)( end - p ) )
  221.         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
  222.  
  223.     memcpy( session, p, sizeof( mbedtls_ssl_session ) );
  224.     p += sizeof( mbedtls_ssl_session );
  225.  
  226. #if defined(MBEDTLS_X509_CRT_PARSE_C)
  227.     if( 3 > (size_t)( end - p ) )
  228.         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
  229.  
  230.     cert_len = ( p[0] << 16 ) | ( p[1] << 8 ) | p[2];
  231.     p += 3;
  232.  
  233.     if( cert_len == 0 )
  234.     {
  235.         session->peer_cert = NULL;
  236.     }
  237.     else
  238.     {
  239.         int ret;
  240.  
  241.         if( cert_len > (size_t)( end - p ) )
  242.             return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
  243.  
  244.         session->peer_cert = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) );
  245.  
  246.         if( session->peer_cert == NULL )
  247.             return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
  248.  
  249.         mbedtls_x509_crt_init( session->peer_cert );
  250.  
  251.         if( ( ret = mbedtls_x509_crt_parse_der( session->peer_cert,
  252.                                                 p, cert_len ) ) != 0 )
  253.         {
  254.             mbedtls_x509_crt_free( session->peer_cert );
  255.             mbedtls_free( session->peer_cert );
  256.             session->peer_cert = NULL;
  257.             return( ret );
  258.         }
  259.  
  260.         p += cert_len;
  261.     }
  262. #endif /* MBEDTLS_X509_CRT_PARSE_C */
  263.  
  264.     if( p != end )
  265.         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
  266.  
  267.     return( 0 );
  268. }
  269.  
  270. /*
  271.  * Create session ticket, with the following structure:
  272.  *
  273.  *    struct {
  274.  *        opaque key_name[4];
  275.  *        opaque iv[12];
  276.  *        opaque encrypted_state<0..2^16-1>;
  277.  *        opaque tag[16];
  278.  *    } ticket;
  279.  *
  280.  * The key_name, iv, and length of encrypted_state are the additional
  281.  * authenticated data.
  282.  */
  283. int mbedtls_ssl_ticket_write( void *p_ticket,
  284.                               const mbedtls_ssl_session *session,
  285.                               unsigned char *start,
  286.                               const unsigned char *end,
  287.                               size_t *tlen,
  288.                               uint32_t *ticket_lifetime )
  289. {
  290.     int ret;
  291.     mbedtls_ssl_ticket_context *ctx = p_ticket;
  292.     mbedtls_ssl_ticket_key *key;
  293.     unsigned char *key_name = start;
  294.     unsigned char *iv = start + 4;
  295.     unsigned char *state_len_bytes = iv + 12;
  296.     unsigned char *state = state_len_bytes + 2;
  297.     unsigned char *tag;
  298.     size_t clear_len, ciph_len;
  299.  
  300.     *tlen = 0;
  301.  
  302.     if( ctx == NULL || ctx->f_rng == NULL )
  303.         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
  304.  
  305.     /* We need at least 4 bytes for key_name, 12 for IV, 2 for len 16 for tag,
  306.      * in addition to session itself, that will be checked when writing it. */
  307.     if( end - start < 4 + 12 + 2 + 16 )
  308.         return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
  309.  
  310. #if defined(MBEDTLS_THREADING_C)
  311.     if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
  312.         return( ret );
  313. #endif
  314.  
  315.     if( ( ret = ssl_ticket_update_keys( ctx ) ) != 0 )
  316.         goto cleanup;
  317.  
  318.     key = &ctx->keys[ctx->active];
  319.  
  320.     *ticket_lifetime = ctx->ticket_lifetime;
  321.  
  322.     memcpy( key_name, key->name, 4 );
  323.  
  324.     if( ( ret = ctx->f_rng( ctx->p_rng, iv, 12 ) ) != 0 )
  325.         goto cleanup;
  326.  
  327.     /* Dump session state */
  328.     if( ( ret = ssl_save_session( session,
  329.                                   state, end - state, &clear_len ) ) != 0 ||
  330.         (unsigned long) clear_len > 65535 )
  331.     {
  332.          goto cleanup;
  333.     }
  334.     state_len_bytes[0] = ( clear_len >> 8 ) & 0xff;
  335.     state_len_bytes[1] = ( clear_len      ) & 0xff;
  336.  
  337.     /* Encrypt and authenticate */
  338.     tag = state + clear_len;
  339.     if( ( ret = mbedtls_cipher_auth_encrypt( &key->ctx,
  340.                     iv, 12, key_name, 4 + 12 + 2,
  341.                     state, clear_len, state, &ciph_len, tag, 16 ) ) != 0 )
  342.     {
  343.         goto cleanup;
  344.     }
  345.     if( ciph_len != clear_len )
  346.     {
  347.         ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
  348.         goto cleanup;
  349.     }
  350.  
  351.     *tlen = 4 + 12 + 2 + 16 + ciph_len;
  352.  
  353. cleanup:
  354. #if defined(MBEDTLS_THREADING_C)
  355.     if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
  356.         return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
  357. #endif
  358.  
  359.     return( ret );
  360. }
  361.  
  362. /*
  363.  * Select key based on name
  364.  */
  365. static mbedtls_ssl_ticket_key *ssl_ticket_select_key(
  366.         mbedtls_ssl_ticket_context *ctx,
  367.         const unsigned char name[4] )
  368. {
  369.     unsigned char i;
  370.  
  371.     for( i = 0; i < sizeof( ctx->keys ) / sizeof( *ctx->keys ); i++ )
  372.         if( memcmp( name, ctx->keys[i].name, 4 ) == 0 )
  373.             return( &ctx->keys[i] );
  374.  
  375.     return( NULL );
  376. }
  377.  
  378. /*
  379.  * Load session ticket (see mbedtls_ssl_ticket_write for structure)
  380.  */
  381. int mbedtls_ssl_ticket_parse( void *p_ticket,
  382.                               mbedtls_ssl_session *session,
  383.                               unsigned char *buf,
  384.                               size_t len )
  385. {
  386.     int ret;
  387.     mbedtls_ssl_ticket_context *ctx = p_ticket;
  388.     mbedtls_ssl_ticket_key *key;
  389.     unsigned char *key_name = buf;
  390.     unsigned char *iv = buf + 4;
  391.     unsigned char *enc_len_p = iv + 12;
  392.     unsigned char *ticket = enc_len_p + 2;
  393.     unsigned char *tag;
  394.     size_t enc_len, clear_len;
  395.  
  396.     if( ctx == NULL || ctx->f_rng == NULL )
  397.         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
  398.  
  399.     /* See mbedtls_ssl_ticket_write() */
  400.     if( len < 4 + 12 + 2 + 16 )
  401.         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
  402.  
  403. #if defined(MBEDTLS_THREADING_C)
  404.     if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
  405.         return( ret );
  406. #endif
  407.  
  408.     if( ( ret = ssl_ticket_update_keys( ctx ) ) != 0 )
  409.         goto cleanup;
  410.  
  411.     enc_len = ( enc_len_p[0] << 8 ) | enc_len_p[1];
  412.     tag = ticket + enc_len;
  413.  
  414.     if( len != 4 + 12 + 2 + enc_len + 16 )
  415.     {
  416.         ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
  417.         goto cleanup;
  418.     }
  419.  
  420.     /* Select key */
  421.     if( ( key = ssl_ticket_select_key( ctx, key_name ) ) == NULL )
  422.     {
  423.         /* We can't know for sure but this is a likely option unless we're
  424.          * under attack - this is only informative anyway */
  425.         ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;
  426.         goto cleanup;
  427.     }
  428.  
  429.     /* Decrypt and authenticate */
  430.     if( ( ret = mbedtls_cipher_auth_decrypt( &key->ctx, iv, 12,
  431.                     key_name, 4 + 12 + 2, ticket, enc_len,
  432.                     ticket, &clear_len, tag, 16 ) ) != 0 )
  433.     {
  434.         if( ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED )
  435.             ret = MBEDTLS_ERR_SSL_INVALID_MAC;
  436.  
  437.         goto cleanup;
  438.     }
  439.     if( clear_len != enc_len )
  440.     {
  441.         ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
  442.         goto cleanup;
  443.     }
  444.  
  445.     /* Actually load session */
  446.     if( ( ret = ssl_load_session( session, ticket, clear_len ) ) != 0 )
  447.         goto cleanup;
  448.  
  449. #if defined(MBEDTLS_HAVE_TIME)
  450.     {
  451.         /* Check for expiration */
  452.         mbedtls_time_t current_time = mbedtls_time( NULL );
  453.  
  454.         if( current_time < session->start ||
  455.             (uint32_t)( current_time - session->start ) > ctx->ticket_lifetime )
  456.         {
  457.             ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;
  458.             goto cleanup;
  459.         }
  460.     }
  461. #endif
  462.  
  463. cleanup:
  464. #if defined(MBEDTLS_THREADING_C)
  465.     if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
  466.         return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
  467. #endif
  468.  
  469.     return( ret );
  470. }
  471.  
  472. /*
  473.  * Free context
  474.  */
  475. void mbedtls_ssl_ticket_free( mbedtls_ssl_ticket_context *ctx )
  476. {
  477.     mbedtls_cipher_free( &ctx->keys[0].ctx );
  478.     mbedtls_cipher_free( &ctx->keys[1].ctx );
  479.  
  480. #if defined(MBEDTLS_THREADING_C)
  481.     mbedtls_mutex_free( &ctx->mutex );
  482. #endif
  483.  
  484.     mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ssl_ticket_context ) );
  485. }
  486.  
  487. #endif /* MBEDTLS_SSL_TICKET_C */
  488.