Webserver+3d print

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers tls_cache.c Source File

tls_cache.c

Go to the documentation of this file.
00001 /**
00002  * @file tls_cache.c
00003  * @brief Session cache management
00004  *
00005  * @section License
00006  *
00007  * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
00008  *
00009  * This file is part of CycloneSSL Open.
00010  *
00011  * This program is free software; you can redistribute it and/or
00012  * modify it under the terms of the GNU General Public License
00013  * as published by the Free Software Foundation; either version 2
00014  * of the License, or (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software Foundation,
00023  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00024  *
00025  * @author Oryx Embedded SARL (www.oryx-embedded.com)
00026  * @version 1.7.6
00027  **/
00028 
00029 //Switch to the appropriate trace level
00030 #define TRACE_LEVEL TLS_TRACE_LEVEL
00031 
00032 //Dependencies
00033 #include <string.h>
00034 #include "tls.h"
00035 #include "tls_cache.h"
00036 #include "debug.h"
00037 
00038 //Check SSL library configuration
00039 #if (TLS_SUPPORT == ENABLED)
00040 
00041 
00042 /**
00043  * @brief Session cache initialization
00044  * @param[in] size Maximum number of cache entries
00045  * @return Handle referencing the fully initialized session cache
00046  **/
00047 
00048 TlsCache *tlsInitCache(uint_t size)
00049 {
00050    size_t n;
00051    TlsCache *cache;
00052 
00053    //Make sure the parameter is acceptable
00054    if(size < 1)
00055       return NULL;
00056 
00057    //Size of the memory required
00058    n = sizeof(TlsCache) + size * sizeof(TlsSession);
00059 
00060    //Allocate a memory buffer to hold the session cache
00061    cache = tlsAllocMem(n);
00062    //Failed to allocate memory?
00063    if(cache == NULL)
00064       return NULL;
00065 
00066    //Clear memory
00067    memset(cache, 0, n);
00068 
00069    //Create a mutex to prevent simultaneous access to the cache
00070    if(!osCreateMutex(&cache->mutex))
00071    {
00072       //Clean up side effects
00073       tlsFreeMem(cache);
00074       //Report an error
00075       return NULL;
00076    }
00077 
00078    //Save the maximum number of cache entries
00079    cache->size = size;
00080 
00081    //Return a pointer to the newly created cache
00082    return cache;
00083 }
00084 
00085 
00086 /**
00087  * @brief Search the session cache for a given session ID
00088  * @param[in] cache Pointer to the session cache
00089  * @param[in] id Expected session ID
00090  * @param[in] length Length of the session ID
00091  * @return A pointer to the matching session is returned. NULL is returned
00092  *   if the specified ID could not be found in the session cache
00093  **/
00094 
00095 TlsSession *tlsFindCache(TlsCache *cache, const uint8_t *id, size_t length)
00096 {
00097    uint_t i;
00098    systime_t time;
00099    TlsSession *session;
00100 
00101    //Check whether session caching is supported
00102    if(cache == NULL)
00103       return NULL;
00104    //Ensure the session ID is valid
00105    if(id == NULL || length == 0)
00106       return NULL;
00107 
00108    //Get current time
00109    time = osGetSystemTime();
00110 
00111    //Acquire exclusive access to the session cache
00112    osAcquireMutex(&cache->mutex);
00113 
00114    //Flush expired entries
00115    for(i = 0; i < cache->size; i++)
00116    {
00117       //Point to the current entry
00118       session = &cache->sessions[i];
00119 
00120       //Skip unused entries
00121       if(session->idLength)
00122       {
00123          //Outdated entry?
00124          if((time - session->timestamp) >= TLS_SESSION_CACHE_LIFETIME)
00125          {
00126             //This session is no more valid and should be removed from the cache
00127             memset(session, 0, sizeof(TlsSession));
00128          }
00129       }
00130    }
00131 
00132    //Search the cache for the specified session ID
00133    for(i = 0; i < cache->size; i++)
00134    {
00135       //Point to the current entry
00136       session = &cache->sessions[i];
00137 
00138       //Check whether the current identifier matches the specified session ID
00139       if(session->idLength == length && !memcmp(session->id, id, length))
00140       {
00141          //Release exclusive access to the session cache
00142          osReleaseMutex(&cache->mutex);
00143          //Return session parameters
00144          return session;
00145       }
00146    }
00147 
00148    //Release exclusive access to the session cache
00149    osReleaseMutex(&cache->mutex);
00150    //No matching entry in session cache
00151    return NULL;
00152 }
00153 
00154 
00155 /**
00156  * @brief Save current session in cache
00157  * @param[in] context TLS context
00158  * @return Error code
00159  **/
00160 
00161 error_t tlsSaveToCache(TlsContext *context)
00162 {
00163    error_t error;
00164    uint_t i;
00165    TlsSession *session;
00166    TlsSession *firstFreeEntry;
00167    TlsSession *oldestEntry;
00168 
00169    //Check parameters
00170    if(context == NULL)
00171       return ERROR_INVALID_PARAMETER;
00172    //Check whether session caching is supported
00173    if(context->cache == NULL)
00174       return ERROR_FAILURE;
00175    //Ensure the session ID is valid
00176    if(context->sessionIdLen == 0)
00177       return NO_ERROR;
00178 
00179    //Acquire exclusive access to the session cache
00180    osAcquireMutex(&context->cache->mutex);
00181 
00182    //Keep track of the first free entry
00183    firstFreeEntry = NULL;
00184    //Keep track of the oldest entry
00185    oldestEntry = NULL;
00186 
00187    //Search the cache for the specified session ID
00188    for(i = 0; i < context->cache->size; i++)
00189    {
00190       //Point to the current entry
00191       session = &context->cache->sessions[i];
00192 
00193       //If the session ID already exists, we are done
00194       if(session->idLength == context->sessionIdLen &&
00195          !memcmp(session->id, context->sessionId, session->idLength))
00196       {
00197          //Do not write to session cache
00198          firstFreeEntry = NULL;
00199          oldestEntry = NULL;
00200          //Exit immediately
00201          break;
00202       }
00203 
00204       //Check whether current entry is free
00205       if(!session->idLength)
00206       {
00207          //Keep track of the first free entry
00208          if(!firstFreeEntry)
00209             firstFreeEntry = session;
00210       }
00211       else
00212       {
00213          //Keep track of the oldest entry in the table
00214          if(!oldestEntry || timeCompare(session->timestamp, oldestEntry->timestamp) < 0)
00215             oldestEntry = session;
00216       }
00217    }
00218 
00219    //Add current session to cache if necessary
00220    if(firstFreeEntry != NULL)
00221       error = tlsSaveSession(context, firstFreeEntry);
00222    else if(oldestEntry != NULL)
00223       error = tlsSaveSession(context, oldestEntry);
00224    else
00225       error = NO_ERROR;
00226 
00227    //Release exclusive access to the session cache
00228    osReleaseMutex(&context->cache->mutex);
00229    //Return status code
00230    return error;
00231 }
00232 
00233 
00234 /**
00235  * @brief Remove current session from cache
00236  * @param[in] context TLS context
00237  * @return Error code
00238  **/
00239 
00240 error_t tlsRemoveFromCache(TlsContext *context)
00241 {
00242    uint_t i;
00243    TlsSession *session;
00244 
00245    //Check parameters
00246    if(context == NULL)
00247       return ERROR_INVALID_PARAMETER;
00248    //Check whether session caching is supported
00249    if(context->cache == NULL)
00250       return ERROR_FAILURE;
00251 
00252    //Ensure the session ID is valid
00253    if(context->sessionIdLen == 0)
00254       return NO_ERROR;
00255 
00256    //Acquire exclusive access to the session cache
00257    osAcquireMutex(&context->cache->mutex);
00258 
00259    //Search the cache for the specified session ID
00260    for(i = 0; i < context->cache->size; i++)
00261    {
00262       //Point to the current entry
00263       session = &context->cache->sessions[i];
00264 
00265       //Check whether the current identifier matches the specified session ID
00266       if(session->idLength == context->sessionIdLen &&
00267          !memcmp(session->id, context->sessionId, session->idLength))
00268       {
00269          //Drop current entry
00270          memset(session, 0, sizeof(TlsSession));
00271       }
00272    }
00273 
00274    //Release exclusive access to the session cache
00275    osReleaseMutex(&context->cache->mutex);
00276    //Successful processing
00277    return NO_ERROR;
00278 }
00279 
00280 
00281 /**
00282  * @brief Properly dispose a session cache
00283  * @param[in] cache Pointer to the session cache to be released
00284  **/
00285 
00286 void tlsFreeCache(TlsCache *cache)
00287 {
00288    size_t n;
00289 
00290    //Invalid session cache?
00291    if(cache == NULL)
00292       return;
00293 
00294    //Release previously allocated resources
00295    osDeleteMutex(&cache->mutex);
00296 
00297    //Compute the number of bytes allocated for the session cache
00298    n = sizeof(TlsCache) + cache->size * sizeof(TlsSession);
00299 
00300    //Clear the session cache before freeing memory
00301    memset(cache, 0, n);
00302    tlsFreeMem(cache);
00303 }
00304 
00305 #endif
00306