Webserver+3d print

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers tls.c Source File

tls.c

Go to the documentation of this file.
00001 /**
00002  * @file tls.c
00003  * @brief TLS (Transport Layer Security)
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  * @section Description
00026  *
00027  * The TLS protocol provides communications security over the Internet. The
00028  * protocol allows client/server applications to communicate in a way that
00029  * is designed to prevent eavesdropping, tampering, or message forgery
00030  *
00031  * @author Oryx Embedded SARL (www.oryx-embedded.com)
00032  * @version 1.7.6
00033  **/
00034 
00035 //Switch to the appropriate trace level
00036 #define TRACE_LEVEL TLS_TRACE_LEVEL
00037 
00038 //Dependencies
00039 #include <string.h>
00040 #include <ctype.h>
00041 #include "tls.h"
00042 #include "tls_client.h"
00043 #include "tls_server.h"
00044 #include "tls_common.h"
00045 #include "tls_record.h"
00046 #include "tls_misc.h"
00047 #include "x509.h"
00048 #include "pem.h"
00049 #include "debug.h"
00050 
00051 //Check SSL library configuration
00052 #if (TLS_SUPPORT == ENABLED)
00053 
00054 
00055 /**
00056  * @brief TLS context initialization
00057  * @return Handle referencing the fully initialized TLS context
00058  **/
00059 
00060 TlsContext *tlsInit(void)
00061 {
00062    TlsContext *context;
00063 
00064    //Allocate a memory buffer to hold the TLS context
00065    context = tlsAllocMem(sizeof(TlsContext));
00066 
00067    //Successful memory allocation?
00068    if(context != NULL)
00069    {
00070       //Clear TLS context
00071       memset(context, 0, sizeof(TlsContext));
00072 
00073       //Default state
00074       context->state = TLS_STATE_INIT;
00075       //Default operation mode
00076       context->entity = TLS_CONNECTION_END_CLIENT;
00077       //Default TLS version
00078       context->version = TLS_MIN_VERSION;
00079       //Default client authentication mode
00080       context->clientAuthMode = TLS_CLIENT_AUTH_NONE;
00081 
00082 #if (TLS_DH_ANON_SUPPORT == ENABLED || TLS_DHE_RSA_SUPPORT == ENABLED || \
00083    TLS_DHE_DSS_SUPPORT == ENABLED || TLS_DHE_PSK_SUPPORT == ENABLED)
00084       //Initialize Diffie-Hellman context
00085       dhInit(&context->dhContext);
00086 #endif
00087 
00088 #if (TLS_ECDH_ANON_SUPPORT == ENABLED || TLS_ECDHE_RSA_SUPPORT == ENABLED || \
00089    TLS_ECDHE_ECDSA_SUPPORT == ENABLED || TLS_ECDHE_PSK_SUPPORT == ENABLED)
00090       //Initialize ECDH context
00091       ecdhInit(&context->ecdhContext);
00092 #endif
00093 
00094 #if (TLS_RSA_SIGN_SUPPORT == ENABLED || TLS_RSA_SUPPORT == ENABLED || \
00095    TLS_DHE_RSA_SUPPORT == ENABLED || TLS_ECDHE_RSA_SUPPORT == ENABLED)
00096       //Initialize peer's RSA public key
00097       rsaInitPublicKey(&context->peerRsaPublicKey);
00098 #endif
00099 
00100 #if (TLS_DSA_SIGN_SUPPORT == ENABLED || TLS_DHE_DSS_SUPPORT == ENABLED)
00101       //Initialize peer's DSA public key
00102       dsaInitPublicKey(&context->peerDsaPublicKey);
00103 #endif
00104 
00105 #if (TLS_ECDSA_SIGN_SUPPORT == ENABLED || TLS_ECDHE_ECDSA_SUPPORT == ENABLED)
00106       //Initialize peer's EC domain parameters
00107       ecInitDomainParameters(&context->peerEcParams);
00108       //Initialize peer's EC public key
00109       ecInit(&context->peerEcPublicKey);
00110 #endif
00111 
00112       //Set the maximum fragment length for outgoing TLS records
00113       context->txRecordMaxLen = TLS_MAX_RECORD_LENGTH;
00114 
00115       //Compute the corresponding buffer size
00116       context->txBufferSize = TLS_MAX_RECORD_LENGTH +
00117          sizeof(TlsRecord) + TLS_MAX_RECORD_OVERHEAD;
00118 
00119       //Save the maximum fragment length for incoming TLS records
00120       context->rxRecordMaxLen = TLS_MAX_RECORD_LENGTH;
00121 
00122       //Compute the corresponding buffer size
00123       context->rxBufferSize = TLS_MAX_RECORD_LENGTH +
00124          sizeof(TlsRecord) + TLS_MAX_RECORD_OVERHEAD;
00125    }
00126 
00127    //Return a pointer to the freshly created TLS context
00128    return context;
00129 }
00130 
00131 
00132 /**
00133  * @brief Set send and receive callbacks (I/O abstraction layer)
00134  * @param[in] context Pointer to the TLS context
00135  * @param[in] handle Handle for I/O operations
00136  * @param[in] sendCallback Send callback function
00137  * @param[in] receiveCallback Receive callback function
00138  * @return Error code
00139  **/
00140 
00141 error_t tlsSetIoCallbacks(TlsContext *context, TlsIoHandle handle,
00142    TlsIoSendCallback sendCallback, TlsIoReceiveCallback receiveCallback)
00143 {
00144    //Check parameters
00145    if(context == NULL || sendCallback == NULL || receiveCallback == NULL)
00146       return ERROR_INVALID_PARAMETER;
00147 
00148    //Save I/O handle
00149    context->handle = handle;
00150 
00151    //Save send and receive callback functions
00152    context->sendCallback = sendCallback;
00153    context->receiveCallback = receiveCallback;
00154 
00155    //Successful processing
00156    return NO_ERROR;
00157 }
00158 
00159 
00160 /**
00161  * @brief Set operation mode (client or server)
00162  * @param[in] context Pointer to the TLS context
00163  * @param[in] entity Specifies whether this entity is considered a client or a server
00164  * @return Error code
00165  **/
00166 
00167 error_t tlsSetConnectionEnd(TlsContext *context, TlsConnectionEnd entity)
00168 {
00169    //Invalid TLS context?
00170    if(context == NULL)
00171       return ERROR_INVALID_PARAMETER;
00172    //Invalid parameter?
00173    if(entity != TLS_CONNECTION_END_CLIENT && entity != TLS_CONNECTION_END_SERVER)
00174       return ERROR_INVALID_PARAMETER;
00175 
00176    //Check whether TLS operates as a client or a server
00177    context->entity = entity;
00178 
00179    //Successful processing
00180    return NO_ERROR;
00181 }
00182 
00183 
00184 /**
00185  * @brief Set the pseudo-random number generator to be used
00186  * @param[in] context Pointer to the TLS context
00187  * @param[in] prngAlgo PRNG algorithm
00188  * @param[in] prngContext Pointer to the PRNG context
00189  * @return Error code
00190  **/
00191 
00192 error_t tlsSetPrng(TlsContext *context, const PrngAlgo *prngAlgo, void *prngContext)
00193 {
00194    //Invalid TLS context?
00195    if(context == NULL)
00196       return ERROR_INVALID_PARAMETER;
00197    //Invalid parameters?
00198    if(prngAlgo == NULL || prngContext == NULL)
00199       return ERROR_INVALID_PARAMETER;
00200 
00201    //PRNG algorithm that will be used to generate random numbers
00202    context->prngAlgo = prngAlgo;
00203    //PRNG context
00204    context->prngContext = prngContext;
00205 
00206    //Successful processing
00207    return NO_ERROR;
00208 }
00209 
00210 
00211 /**
00212  * @brief Set the name of the remote server
00213  * @param[in] context Pointer to the TLS context
00214  * @param[in] serverName Fully qualified domain name of the server
00215  * @return Error code
00216  **/
00217 
00218 error_t tlsSetServerName(TlsContext *context, const char_t *serverName)
00219 {
00220    size_t i;
00221    size_t length;
00222 
00223    //Invalid parameters?
00224    if(context == NULL || serverName == NULL)
00225       return ERROR_INVALID_PARAMETER;
00226 
00227    //Retrieve the length of the server name
00228    length = strlen(serverName);
00229 
00230    //Check whether the server name has already been configured
00231    if(context->serverName != NULL)
00232    {
00233       //Release memory
00234       tlsFreeMem(context->serverName);
00235       context->serverName = NULL;
00236    }
00237 
00238    //Valid server name?
00239    if(length > 0)
00240    {
00241       //Allocate a memory block to hold the hostname
00242       context->serverName = tlsAllocMem(length + 1);
00243       //Failed to allocate memory?
00244       if(context->serverName == NULL)
00245          return ERROR_OUT_OF_MEMORY;
00246 
00247       //Convert the hostname into lowercase
00248       for(i = 0; i < length; i++)
00249          context->serverName[i] = tolower((uint8_t) serverName[i]);
00250 
00251       //Properly terminate the string with a NULL character
00252       context->serverName[length] = '\0';
00253    }
00254 
00255    //Successful processing
00256    return NO_ERROR;
00257 }
00258 
00259 
00260 /**
00261  * @brief Set session cache
00262  * @param[in] context Pointer to the TLS context
00263  * @param[in] cache Session cache that will be used to save/resume TLS sessions
00264  * @return Error code
00265  **/
00266 
00267 error_t tlsSetCache(TlsContext *context, TlsCache *cache)
00268 {
00269    //Check parameters
00270    if(context == NULL || cache == NULL)
00271       return ERROR_INVALID_PARAMETER;
00272 
00273    //The cache will be used to save/resume TLS sessions
00274    context->cache = cache;
00275 
00276    //Successful processing
00277    return NO_ERROR;
00278 }
00279 
00280 
00281 /**
00282  * @brief Set client authentication mode
00283  * @param[in] context Pointer to the TLS context
00284  * @param[in] mode Client authentication mode
00285  * @return Error code
00286  **/
00287 
00288 error_t tlsSetClientAuthMode(TlsContext *context, TlsClientAuthMode mode)
00289 {
00290    //Invalid TLS context?
00291    if(context == NULL)
00292       return ERROR_INVALID_PARAMETER;
00293 
00294    //Save client authentication mode
00295    context->clientAuthMode = mode;
00296 
00297    //Successful processing
00298    return NO_ERROR;
00299 }
00300 
00301 
00302 /**
00303  * @brief Set TLS buffer size
00304  * @param[in] context Pointer to the TLS context
00305  * @param[in] txBufferSize TX buffer size
00306  * @param[in] rxBufferSize RX buffer size
00307  * @return Error code
00308  **/
00309 
00310 error_t tlsSetBufferSize(TlsContext *context,
00311    size_t txBufferSize, size_t rxBufferSize)
00312 {
00313    //Invalid TLS context?
00314    if(context == NULL)
00315       return ERROR_INVALID_PARAMETER;
00316    //Check parameters
00317    if(txBufferSize < 512 || rxBufferSize < 512)
00318       return ERROR_INVALID_PARAMETER;
00319 
00320    //Save the maximum fragment length for outgoing TLS records
00321    context->txRecordMaxLen = txBufferSize;
00322 
00323    //Compute the corresponding buffer size
00324    context->txBufferSize = txBufferSize +
00325       sizeof(TlsRecord) + TLS_MAX_RECORD_OVERHEAD;
00326 
00327    //Save the maximum fragment length for incoming TLS records
00328    context->rxRecordMaxLen = rxBufferSize;
00329 
00330    //Compute the corresponding buffer size
00331    context->rxBufferSize = rxBufferSize +
00332       sizeof(TlsRecord) + TLS_MAX_RECORD_OVERHEAD;
00333 
00334    //Successful processing
00335    return NO_ERROR;
00336 }
00337 
00338 
00339 /**
00340  * @brief Specify the list of allowed cipher suites
00341  * @param[in] context Pointer to the TLS context
00342  * @param[in] cipherSuites Pointer to the cipher suite list
00343  * @param[in] length Number of cipher suites in the list
00344  * @return Error code
00345  **/
00346 
00347 error_t tlsSetCipherSuites(TlsContext *context,
00348    const uint16_t *cipherSuites, uint_t length)
00349 {
00350    //Invalid TLS context?
00351    if(context == NULL)
00352       return ERROR_INVALID_PARAMETER;
00353    //Check parameters
00354    if(cipherSuites == NULL && length != 0)
00355       return ERROR_INVALID_PARAMETER;
00356 
00357    //Restrict the cipher suites that can be used
00358    context->cipherSuites = cipherSuites;
00359    context->numCipherSuites = length;
00360 
00361    //Successful processing
00362    return NO_ERROR;
00363 }
00364 
00365 
00366 /**
00367  * @brief Import Diffie-Hellman parameters
00368  * @param[in] context Pointer to the TLS context
00369  * @param[in] params PEM structure that holds Diffie-Hellman parameters
00370  * @param[in] length Total length of the DER structure
00371  * @return Error code
00372  **/
00373 
00374 error_t tlsSetDhParameters(TlsContext *context,
00375    const char_t *params, size_t length)
00376 {
00377 #if (TLS_DH_ANON_SUPPORT == ENABLED || TLS_DHE_RSA_SUPPORT == ENABLED || \
00378    TLS_DHE_DSS_SUPPORT == ENABLED || TLS_DHE_PSK_SUPPORT == ENABLED)
00379    //Invalid TLS context?
00380    if(context == NULL)
00381       return ERROR_INVALID_PARAMETER;
00382    //Check parameters
00383    if(params == NULL && length != 0)
00384       return ERROR_INVALID_PARAMETER;
00385 
00386    //Decode the PEM structure that holds Diffie-Hellman parameters
00387    return pemReadDhParameters(params, length, &context->dhContext.params);
00388 #else
00389    //Diffie-Hellman is not implemented
00390    return ERROR_NOT_IMPLEMENTED;
00391 #endif
00392 }
00393 
00394 
00395 /**
00396  * @brief Set the list of supported ALPN protocols
00397  * @param[in] context Pointer to the TLS context
00398  * @param[in] protocolList Comma-delimited list of supported protocols
00399  * @return Error code
00400  **/
00401 
00402 error_t tlsSetAlpnProtocolList(TlsContext *context, const char_t *protocolList)
00403 {
00404 #if (TLS_ALPN_SUPPORT == ENABLED)
00405    size_t length;
00406 
00407    //Invalid parameters?
00408    if(context == NULL || protocolList == NULL)
00409       return ERROR_INVALID_PARAMETER;
00410 
00411    //Retrieve the length of the list
00412    length = strlen(protocolList);
00413 
00414    //Check whether the list of supported protocols has already been configured
00415    if(context->protocolList != NULL)
00416    {
00417       //Release memory
00418       tlsFreeMem(context->protocolList);
00419       context->protocolList = NULL;
00420    }
00421 
00422    //Check whether the list of protocols is valid
00423    if(length > 0)
00424    {
00425       //Allocate a memory block to hold the list
00426       context->protocolList = tlsAllocMem(length + 1);
00427       //Failed to allocate memory?
00428       if(context->protocolList == NULL)
00429          return ERROR_OUT_OF_MEMORY;
00430 
00431       //Save the list of supported protocols
00432       strcpy(context->protocolList, protocolList);
00433    }
00434 
00435    //Successful processing
00436    return NO_ERROR;
00437 #else
00438    //ALPN is not implemented
00439    return ERROR_NOT_IMPLEMENTED;
00440 #endif
00441 }
00442 
00443 
00444 /**
00445  * @brief Get the name of the negotiated ALPN protocol
00446  * @param[in] context Pointer to the TLS context
00447  * @return Pointer to the protocol name
00448  **/
00449 
00450 const char_t *tlsGetAlpnProtocol(TlsContext *context)
00451 {
00452    //Not implemented
00453    return NULL;
00454 }
00455 
00456 
00457 /**
00458  * @brief Set the pre-shared key to be used
00459  * @param[in] context Pointer to the TLS context
00460  * @param[in] psk Pointer to the pre-shared key
00461  * @param[in] pskLength Length of the pre-shared key, in bytes
00462  * @return Error code
00463  **/
00464 
00465 error_t tlsSetPsk(TlsContext *context, const uint8_t *psk, size_t pskLength)
00466 {
00467 #if (TLS_PSK_SUPPORT == ENABLED || TLS_RSA_PSK_SUPPORT == ENABLED || \
00468    TLS_DHE_PSK_SUPPORT == ENABLED || TLS_ECDHE_PSK_SUPPORT == ENABLED)
00469    //Invalid TLS context?
00470    if(context == NULL)
00471       return ERROR_INVALID_PARAMETER;
00472    //Check parameters
00473    if(psk == NULL && pskLength != 0)
00474       return ERROR_INVALID_PARAMETER;
00475 
00476    //Check whether the pre-shared key has already been configured
00477    if(context->psk != NULL)
00478    {
00479       //Release memory
00480       memset(context->psk, 0, context->pskLen);
00481       tlsFreeMem(context->psk);
00482       //Re-initialize length
00483       context->pskLen = 0;
00484    }
00485 
00486    //Valid PSK?
00487    if(pskLength > 0)
00488    {
00489       //Allocate a memory block to hold the pre-shared key
00490       context->psk = tlsAllocMem(pskLength);
00491       //Failed to allocate memory?
00492       if(context->psk == NULL)
00493          return ERROR_OUT_OF_MEMORY;
00494 
00495       //Save the pre-shared key
00496       memcpy(context->psk, psk, pskLength);
00497       //Save the length of the key
00498       context->pskLen = pskLength;
00499    }
00500 
00501    //Successful processing
00502    return NO_ERROR;
00503 #else
00504    //PSK key exchange is not implemented
00505    return ERROR_NOT_IMPLEMENTED;
00506 #endif
00507 }
00508 
00509 
00510 /**
00511  * @brief Set the PSK identity to be used by the client
00512  * @param[in] context Pointer to the TLS context
00513  * @param[in] pskIdentity NULL-terminated string that contains the PSK identity
00514  * @return Error code
00515  **/
00516 
00517 error_t tlsSetPskIdentity(TlsContext *context, const char_t *pskIdentity)
00518 {
00519 #if (TLS_PSK_SUPPORT == ENABLED || TLS_RSA_PSK_SUPPORT == ENABLED || \
00520    TLS_DHE_PSK_SUPPORT == ENABLED || TLS_ECDHE_PSK_SUPPORT == ENABLED)
00521    size_t length;
00522 
00523    //Invalid parameters?
00524    if(context == NULL || pskIdentity == NULL)
00525       return ERROR_INVALID_PARAMETER;
00526 
00527    //Retrieve the length of the PSK identity
00528    length = strlen(pskIdentity);
00529 
00530    //Check whether the PSK identity has already been configured
00531    if(context->pskIdentity != NULL)
00532    {
00533       //Release memory
00534       tlsFreeMem(context->pskIdentity);
00535       context->pskIdentity = NULL;
00536    }
00537 
00538    //Valid PSK identity?
00539    if(length > 0)
00540    {
00541       //Allocate a memory block to hold the PSK identity
00542       context->pskIdentity = tlsAllocMem(length + 1);
00543       //Failed to allocate memory?
00544       if(context->pskIdentity == NULL)
00545          return ERROR_OUT_OF_MEMORY;
00546 
00547       //Save the PSK identity
00548       strcpy(context->pskIdentity, pskIdentity);
00549    }
00550 
00551    //Successful processing
00552    return NO_ERROR;
00553 #else
00554    //PSK key exchange is not implemented
00555    return ERROR_NOT_IMPLEMENTED;
00556 #endif
00557 }
00558 
00559 
00560 /**
00561  * @brief Set the PSK identity hint to be used by the server
00562  * @param[in] context Pointer to the TLS context
00563  * @param[in] pskIdentityHint NULL-terminated string that contains the PSK identity hint
00564  * @return Error code
00565  **/
00566 
00567 error_t tlsSetPskIdentityHint(TlsContext *context, const char_t *pskIdentityHint)
00568 {
00569 #if (TLS_PSK_SUPPORT == ENABLED || TLS_RSA_PSK_SUPPORT == ENABLED || \
00570    TLS_DHE_PSK_SUPPORT == ENABLED || TLS_ECDHE_PSK_SUPPORT == ENABLED)
00571    size_t length;
00572 
00573    //Invalid parameters?
00574    if(context == NULL || pskIdentityHint == NULL)
00575       return ERROR_INVALID_PARAMETER;
00576 
00577    //Retrieve the length of the PSK identity hint
00578    length = strlen(pskIdentityHint);
00579 
00580    //Check whether the PSK identity hint has already been configured
00581    if(context->pskIdentityHint != NULL)
00582    {
00583       //Release memory
00584       tlsFreeMem(context->pskIdentityHint);
00585       context->pskIdentityHint = NULL;
00586    }
00587 
00588    //Valid PSK identity hint?
00589    if(length > 0)
00590    {
00591       //Allocate a memory block to hold the PSK identity hint
00592       context->pskIdentityHint = tlsAllocMem(length + 1);
00593       //Failed to allocate memory?
00594       if(context->pskIdentityHint == NULL)
00595          return ERROR_OUT_OF_MEMORY;
00596 
00597       //Save the PSK identity hint
00598       strcpy(context->pskIdentityHint, pskIdentityHint);
00599    }
00600 
00601    //Successful processing
00602    return NO_ERROR;
00603 #else
00604    //PSK key exchange is not implemented
00605    return ERROR_NOT_IMPLEMENTED;
00606 #endif
00607 }
00608 
00609 
00610 /**
00611  * @brief Register the PSK callback function
00612  * @param[in] context Pointer to the TLS context
00613  * @param[in] pskCallback PSK callback function
00614  * @return Error code
00615  **/
00616 
00617 error_t tlsSetPskCallback(TlsContext *context, TlsPskCallback pskCallback)
00618 {
00619 #if (TLS_PSK_SUPPORT == ENABLED || TLS_RSA_PSK_SUPPORT == ENABLED || \
00620    TLS_DHE_PSK_SUPPORT == ENABLED || TLS_ECDHE_PSK_SUPPORT == ENABLED)
00621    //Invalid parameters?
00622    if(context == NULL || pskCallback == NULL)
00623       return ERROR_INVALID_PARAMETER;
00624 
00625    //Save the PSK callback function
00626    context->pskCallback = pskCallback;
00627 
00628    //Successful processing
00629    return NO_ERROR;
00630 #else
00631    //PSK key exchange is not implemented
00632    return ERROR_NOT_IMPLEMENTED;
00633 #endif
00634 }
00635 
00636 
00637 /**
00638  * @brief Import a trusted CA list
00639  * @param[in] context Pointer to the TLS context
00640  * @param[in] trustedCaList List of trusted CA (PEM format)
00641  * @param[in] length Total length of the list
00642  * @return Error code
00643  **/
00644 
00645 error_t tlsSetTrustedCaList(TlsContext *context,
00646    const char_t *trustedCaList, size_t length)
00647 {
00648    //Invalid TLS context?
00649    if(context == NULL)
00650       return ERROR_INVALID_PARAMETER;
00651    //Check parameters
00652    if(trustedCaList == NULL && length != 0)
00653       return ERROR_INVALID_PARAMETER;
00654 
00655    //Save the certificate chain
00656    context->trustedCaList = trustedCaList;
00657    context->trustedCaListLen = length;
00658 
00659    //Successful processing
00660    return NO_ERROR;
00661 }
00662 
00663 
00664 /**
00665  * @brief Import a certificate and the corresponding private key
00666  * @param[in] context Pointer to the TLS context
00667  * @param[in] certChain Certificate chain (PEM format)
00668  * @param[in] certChainLength Total length of the certificate chain
00669  * @param[in] privateKey Private key (PEM format)
00670  * @param[in] privateKeyLength Total length of the private key
00671  * @return Error code
00672  **/
00673 
00674 error_t tlsAddCertificate(TlsContext *context, const char_t *certChain,
00675    size_t certChainLength, const char_t *privateKey, size_t privateKeyLength)
00676 {
00677    error_t error;
00678    const char_t *p;
00679    size_t n;
00680    uint8_t *derCert;
00681    size_t derCertSize;
00682    size_t derCertLength;
00683    X509CertificateInfo *certInfo;
00684    TlsCertificateType certType;
00685    TlsSignatureAlgo certSignAlgo;
00686    TlsHashAlgo certHashAlgo;
00687    TlsEcNamedCurve namedCurve;
00688 
00689    //Invalid TLS context?
00690    if(context == NULL)
00691       return ERROR_INVALID_PARAMETER;
00692 
00693    //Check parameters
00694    if(certChain == NULL || certChainLength == 0)
00695       return ERROR_INVALID_PARAMETER;
00696    if(privateKey == NULL || privateKeyLength == 0)
00697       return ERROR_INVALID_PARAMETER;
00698 
00699    //Make sure there is enough room to add the certificate
00700    if(context->numCerts >= TLS_MAX_CERTIFICATES)
00701       return ERROR_OUT_OF_RESOURCES;
00702 
00703    //Allocate a memory buffer to store X.509 certificate info
00704    certInfo = tlsAllocMem(sizeof(X509CertificateInfo));
00705    //Failed to allocate memory?
00706    if(certInfo == NULL)
00707       return ERROR_OUT_OF_MEMORY;
00708 
00709    //Point to the beginning of the certificate chain
00710    p = certChain;
00711    n = certChainLength;
00712 
00713    //DER encoded certificate
00714    derCert = NULL;
00715    derCertSize = 0;
00716    derCertLength = 0;
00717 
00718    //Start of exception handling block
00719    do
00720    {
00721       //Decode end entity certificate
00722       error = pemReadCertificate(&p, &n, &derCert, &derCertSize, &derCertLength);
00723       //Any error to report?
00724       if(error)
00725          break;
00726 
00727       //Parse X.509 certificate
00728       error = x509ParseCertificate(derCert, derCertLength, certInfo);
00729       //Failed to parse the X.509 certificate?
00730       if(error)
00731          break;
00732 
00733       //Retrieve the signature algorithm that has been used to sign the certificate
00734       error = tlsGetCertificateType(certInfo, &certType,
00735          &certSignAlgo, &certHashAlgo, &namedCurve);
00736       //The specified signature algorithm is not supported?
00737       if(error)
00738          break;
00739 
00740       //End of exception handling block
00741    } while(0);
00742 
00743    //Check whether the certificate is acceptable
00744    if(!error)
00745    {
00746       //Point to the structure that describes the certificate
00747       TlsCertDesc *cert = &context->certs[context->numCerts];
00748 
00749       //Save the certificate chain and the corresponding private key
00750       cert->certChain = certChain;
00751       cert->certChainLength = certChainLength;
00752       cert->privateKey = privateKey;
00753       cert->privateKeyLength = privateKeyLength;
00754       cert->type = certType;
00755       cert->signAlgo = certSignAlgo;
00756       cert->hashAlgo = certHashAlgo;
00757       cert->namedCurve = namedCurve;
00758 
00759       //Update the number of certificates
00760       context->numCerts++;
00761    }
00762 
00763    //Release previously allocated memory
00764    tlsFreeMem(derCert);
00765    tlsFreeMem(certInfo);
00766 
00767    //Return status code
00768    return error;
00769 }
00770 
00771 
00772 /**
00773  * @brief Initiate the TLS handshake
00774  * @param[in] context Pointer to the TLS context
00775  * @return Error code
00776  **/
00777 
00778 error_t tlsConnect(TlsContext *context)
00779 {
00780    error_t error;
00781 
00782    //Invalid TLS context?
00783    if(context == NULL)
00784       return ERROR_INVALID_PARAMETER;
00785 
00786    //Ensure the I/O callback functions are properly registered
00787    if(context->sendCallback == NULL || context->receiveCallback == NULL)
00788       return ERROR_NOT_CONFIGURED;
00789 
00790    //Verify that the PRNG is properly set
00791    if(context->prngAlgo == NULL || context->prngContext == NULL)
00792       return ERROR_NOT_CONFIGURED;
00793 
00794    //Check current state
00795    if(context->state == TLS_STATE_INIT)
00796    {
00797       //Allocate send buffer if necessary
00798       if(context->txBuffer == NULL)
00799       {
00800          //Allocate TX buffer
00801          context->txBuffer = tlsAllocMem(context->txBufferSize);
00802 
00803          //Failed to allocate memory?
00804          if(context->txBuffer == NULL)
00805             return ERROR_OUT_OF_MEMORY;
00806 
00807          //Clear TX buffer
00808          memset(context->txBuffer, 0, context->txBufferSize);
00809       }
00810 
00811       //Allocate receive buffer if necessary
00812       if(context->rxBuffer == NULL)
00813       {
00814          //Allocate RX buffer
00815          context->rxBuffer = tlsAllocMem(context->rxBufferSize);
00816 
00817          //Failed to allocate memory?
00818          if(context->rxBuffer == NULL)
00819          {
00820             //Clean up side effects
00821             tlsFreeMem(context->txBuffer);
00822             context->txBuffer = NULL;
00823             //Report an error
00824             return ERROR_OUT_OF_MEMORY;
00825          }
00826 
00827          //Clear RX buffer
00828          memset(context->rxBuffer, 0, context->rxBufferSize);
00829       }
00830    }
00831 
00832    //Perform TLS handshake
00833    error = tlsHandshake(context);
00834    //Return status code
00835    return error;
00836 }
00837 
00838 
00839 /**
00840  * @brief Send application data to the remote host using TLS
00841  * @param[in] context Pointer to the TLS context
00842  * @param[in] data Pointer to a buffer containing the data to be transmitted
00843  * @param[in] length Number of bytes to be transmitted
00844  * @param[out] written Actual number of bytes written (optional parameter)
00845  * @param[in] flags Set of flags that influences the behavior of this function
00846  * @return Error code
00847  **/
00848 
00849 error_t tlsWrite(TlsContext *context, const void *data,
00850    size_t length, size_t *written, uint_t flags)
00851 {
00852    error_t error;
00853    size_t n;
00854    size_t totalLength;
00855 
00856    //Invalid TLS context?
00857    if(context == NULL)
00858       return ERROR_INVALID_PARAMETER;
00859 
00860    //Check parameters
00861    if(data == NULL && length != 0)
00862       return ERROR_INVALID_PARAMETER;
00863 
00864    //Ensure the I/O callback functions are properly registered
00865    if(context->sendCallback == NULL || context->receiveCallback == NULL)
00866       return ERROR_NOT_CONFIGURED;
00867 
00868    //Initialize status code
00869    error = NO_ERROR;
00870 
00871    //Actual number of bytes written
00872    totalLength = 0;
00873 
00874    //Send as much data as possible
00875    while(totalLength < length)
00876    {
00877       //Check current state
00878       if(context->state == TLS_STATE_APPLICATION_DATA)
00879       {
00880          //Calculate the number of bytes to write at a time
00881          n = MIN(length - totalLength, context->txRecordMaxLen);
00882          //The record length must not exceed 16384 bytes
00883          n = MIN(n, TLS_MAX_RECORD_LENGTH);
00884 
00885          //Send application data
00886          error = tlsWriteProtocolData(context, data, n, TLS_TYPE_APPLICATION_DATA);
00887 
00888          //Check status code
00889          if(!error)
00890          {
00891             //Advance data pointer
00892             data = (uint8_t *) data + n;
00893             //Update byte counter
00894             totalLength += n;
00895          }
00896          else
00897          {
00898             //Send an alert message to the peer, if applicable
00899             tlsProcessError(context, error);
00900          }
00901       }
00902       else
00903       {
00904          //The connection has not yet been established
00905          error = ERROR_NOT_CONNECTED;
00906       }
00907 
00908       //Any error to report?
00909       if(error)
00910          break;
00911    }
00912 
00913    //Total number of data that have been written
00914    if(written != NULL)
00915       *written = totalLength;
00916 
00917    //Return status code
00918    return error;
00919 }
00920 
00921 
00922 /**
00923  * @brief Receive application data from a the remote host using TLS
00924  * @param[in] context Pointer to the TLS context
00925  * @param[out] data Buffer into which received data will be placed
00926  * @param[in] size Maximum number of bytes that can be received
00927  * @param[out] received Number of bytes that have been received
00928  * @param[in] flags Set of flags that influences the behavior of this function
00929  * @return Error code
00930  **/
00931 
00932 error_t tlsRead(TlsContext *context, void *data,
00933    size_t size, size_t *received, uint_t flags)
00934 {
00935    error_t error;
00936    size_t i;
00937    size_t n;
00938    uint8_t *p;
00939    TlsContentType contentType;
00940 
00941    //Invalid TLS context?
00942    if(context == NULL)
00943       return ERROR_INVALID_PARAMETER;
00944 
00945    //Check parameters
00946    if(data == NULL && received == NULL)
00947       return ERROR_INVALID_PARAMETER;
00948 
00949    //Ensure the I/O callback functions are properly registered
00950    if(context->sendCallback == NULL || context->receiveCallback == NULL)
00951       return ERROR_NOT_CONFIGURED;
00952 
00953    //Initialize status code
00954    error = NO_ERROR;
00955 
00956    //No data has been read yet
00957    *received = 0;
00958 
00959    //Read as much data as possible
00960    while(*received < size)
00961    {
00962       //Check current state
00963       if(context->state == TLS_STATE_APPLICATION_DATA)
00964       {
00965          //The TLS record layer receives uninterpreted data from higher layers
00966          error = tlsReadProtocolData(context, (void **) &p, &n, &contentType);
00967 
00968          //Check status code
00969          if(!error)
00970          {
00971             //Application data received?
00972             if(contentType == TLS_TYPE_APPLICATION_DATA)
00973             {
00974                //Limit the number of bytes to read at a time
00975                n = MIN(n, size - *received);
00976 
00977                //The TLS_FLAG_BREAK_CHAR flag causes the function to stop reading
00978                //data as soon as the specified break character is encountered
00979                if(flags & TLS_FLAG_BREAK_CHAR)
00980                {
00981                   //Retrieve the break character code
00982                   char_t c = LSB(flags);
00983 
00984                   //Search for the specified break character
00985                   for(i = 0; i < n && p[i] != c; i++);
00986                   //Adjust the number of data to read
00987                   n = MIN(n, i + 1);
00988 
00989                   //Copy data to user buffer
00990                   memcpy(data, p, n);
00991                   //Total number of data that have been read
00992                   *received += n;
00993 
00994                   //Advance data pointer
00995                   context->rxBufferPos += n;
00996                   //Number of bytes still pending in the receive buffer
00997                   context->rxBufferLen -= n;
00998 
00999                   //Check whether a break character has been found
01000                   if(n > 0 && p[n - 1] == c)
01001                      break;
01002                }
01003                else
01004                {
01005                   //Copy data to user buffer
01006                   memcpy(data, p, n);
01007                   //Total number of data that have been read
01008                   *received += n;
01009 
01010                   //Advance data pointer
01011                   context->rxBufferPos += n;
01012                   //Number of bytes still pending in the receive buffer
01013                   context->rxBufferLen -= n;
01014 
01015                   //The TLS_FLAG_WAIT_ALL flag causes the function to return
01016                   //only when the requested number of bytes have been read
01017                   if(!(flags & TLS_FLAG_WAIT_ALL))
01018                      break;
01019                }
01020 
01021                //Advance data pointer
01022                data = (uint8_t *) data + n;
01023             }
01024             //Alert message received?
01025             else if(contentType == TLS_TYPE_ALERT)
01026             {
01027                //Parse Alert message
01028                error = tlsParseAlert(context, (TlsAlert *) p, n);
01029 
01030                //Advance data pointer
01031                context->rxBufferPos += n;
01032                //Number of bytes still pending in the receive buffer
01033                context->rxBufferLen -= n;
01034             }
01035             //An inappropriate message was received?
01036             else
01037             {
01038                //Report an error
01039                error = ERROR_UNEXPECTED_MESSAGE;
01040             }
01041          }
01042 
01043          //Any error to report?
01044          if(error)
01045          {
01046             //Send an alert message to the peer, if applicable
01047             tlsProcessError(context, error);
01048          }
01049       }
01050       else if(context->state == TLS_STATE_CLOSING ||
01051          context->state == TLS_STATE_CLOSED)
01052       {
01053          //Check whether a fatal alert message has been sent or received
01054          if(context->fatalAlertSent || context->fatalAlertReceived)
01055          {
01056             //Alert messages with a level of fatal result in the immediate
01057             //termination of the connection
01058             error = ERROR_FAILURE;
01059          }
01060          else
01061          {
01062             //The user must be satisfied with data already on hand
01063             if(*received > 0)
01064             {
01065                //Some data are pending in the receive buffer
01066                error = NO_ERROR;
01067                break;
01068             }
01069             else
01070             {
01071                //The receive buffer is empty
01072                error = ERROR_END_OF_STREAM;
01073             }
01074          }
01075       }
01076       else
01077       {
01078          //The connection has not yet been established
01079          error = ERROR_NOT_CONNECTED;
01080       }
01081 
01082       //Any error to report?
01083       if(error)
01084          break;
01085    }
01086 
01087    //Return status code
01088    return error;
01089 }
01090 
01091 
01092 /**
01093  * @brief Gracefully close TLS session
01094  * @param[in] context Pointer to the TLS context
01095  **/
01096 
01097 error_t tlsShutdown(TlsContext *context)
01098 {
01099    //Either party may initiate a close by sending a close_notify alert
01100    return tlsShutdownEx(context, FALSE);
01101 }
01102 
01103 
01104 /**
01105  * @brief Gracefully close TLS session
01106  * @param[in] context Pointer to the TLS context
01107  * @param[in] waitForCloseNotify Wait for the close notify alert from the peer
01108  **/
01109 
01110 error_t tlsShutdownEx(TlsContext *context, bool_t waitForCloseNotify)
01111 {
01112    error_t error;
01113    size_t n;
01114    uint8_t *p;
01115    TlsContentType contentType;
01116 
01117    //Invalid TLS context?
01118    if(context == NULL)
01119       return ERROR_INVALID_PARAMETER;
01120 
01121    //Ensure the I/O callback functions are properly registered
01122    if(context->sendCallback == NULL || context->receiveCallback == NULL)
01123       return ERROR_NOT_CONFIGURED;
01124 
01125    //Initialize status code
01126    error = NO_ERROR;
01127 
01128    //Wait for the TLS session to be closed
01129    while(context->state != TLS_STATE_CLOSED)
01130    {
01131       //Check current state
01132       if(context->state == TLS_STATE_APPLICATION_DATA)
01133       {
01134          //Flush send buffer
01135          error = tlsWriteProtocolData(context, NULL, 0, TLS_TYPE_NONE);
01136 
01137          //Check status code
01138          if(!error)
01139          {
01140             //Either party may initiate a close by sending a close_notify alert
01141             context->state = TLS_STATE_CLOSING;
01142          }
01143       }
01144       if(context->state == TLS_STATE_CLOSING)
01145       {
01146          //Flush send buffer
01147          error = tlsWriteProtocolData(context, NULL, 0, TLS_TYPE_NONE);
01148 
01149          //Check status code
01150          if(!error)
01151          {
01152             //Unless some other fatal alert has been transmitted, each party
01153             //is required to send a close_notify alert before closing the
01154             //write side of the connection
01155             if(context->fatalAlertSent || context->fatalAlertReceived)
01156             {
01157                //Close the connection immediately
01158                context->state = TLS_STATE_CLOSED;
01159             }
01160             else if(!context->closeNotifySent)
01161             {
01162                //Notifies the recipient that the sender will not send any
01163                //more messages on this connection
01164                error = tlsSendAlert(context, TLS_ALERT_LEVEL_WARNING,
01165                   TLS_ALERT_CLOSE_NOTIFY);
01166             }
01167             else if(!context->closeNotifyReceived && waitForCloseNotify)
01168             {
01169                //Wait for the responding close_notify alert
01170                error = tlsReadProtocolData(context, (void **) &p, &n, &contentType);
01171 
01172                //Check status code
01173                if(!error)
01174                {
01175                   //Application data received?
01176                   if(contentType == TLS_TYPE_APPLICATION_DATA)
01177                   {
01178                      //Advance data pointer
01179                      context->rxBufferPos += n;
01180                      //Number of bytes still pending in the receive buffer
01181                      context->rxBufferLen -= n;
01182                   }
01183                   //Alert message received?
01184                   else if(contentType == TLS_TYPE_ALERT)
01185                   {
01186                      //Parse Alert message
01187                      error = tlsParseAlert(context, (TlsAlert *) p, n);
01188 
01189                      //Advance data pointer
01190                      context->rxBufferPos += n;
01191                      //Number of bytes still pending in the receive buffer
01192                      context->rxBufferLen -= n;
01193                   }
01194                   //An inappropriate message was received?
01195                   else
01196                   {
01197                      //Report an error
01198                      error = ERROR_UNEXPECTED_MESSAGE;
01199                   }
01200                }
01201             }
01202             else
01203             {
01204                //The connection is closed
01205                context->state = TLS_STATE_CLOSED;
01206             }
01207          }
01208       }
01209       else
01210       {
01211          //Report an error
01212          error = ERROR_NOT_CONNECTED;
01213       }
01214 
01215       //Any error to report?
01216       if(error)
01217          break;
01218    }
01219 
01220    //Return status code
01221    return error;
01222 }
01223 
01224 
01225 /**
01226  * @brief Release TLS context
01227  * @param[in] context Pointer to the TLS context
01228  **/
01229 
01230 void tlsFree(TlsContext *context)
01231 {
01232    //Valid TLS context?
01233    if(context != NULL)
01234    {
01235       //Release server name
01236       if(context->serverName != NULL)
01237          tlsFreeMem(context->serverName);
01238 
01239 #if (TLS_ALPN_SUPPORT == ENABLED)
01240       //Release the list of supported protocols
01241       if(context->protocolList != NULL)
01242          tlsFreeMem(context->protocolList);
01243 #endif
01244 
01245 #if (TLS_PSK_SUPPORT == ENABLED || TLS_RSA_PSK_SUPPORT == ENABLED || \
01246    TLS_DHE_PSK_SUPPORT == ENABLED || TLS_ECDHE_PSK_SUPPORT == ENABLED)
01247       //Release the pre-shared key
01248       if(context->psk != NULL)
01249       {
01250          memset(context->psk, 0, context->pskLen);
01251          tlsFreeMem(context->psk);
01252       }
01253 
01254       //Release the PSK identity
01255       if(context->pskIdentity != NULL)
01256          tlsFreeMem(context->pskIdentity);
01257 
01258       //Release the PSK identity hint
01259       if(context->pskIdentityHint != NULL)
01260          tlsFreeMem(context->pskIdentityHint);
01261 #endif
01262 
01263 #if (TLS_DH_ANON_SUPPORT == ENABLED || TLS_DHE_RSA_SUPPORT == ENABLED || \
01264    TLS_DHE_DSS_SUPPORT == ENABLED || TLS_DHE_PSK_SUPPORT == ENABLED)
01265       //Release Diffie-Hellman context
01266       dhFree(&context->dhContext);
01267 #endif
01268 
01269 #if (TLS_ECDH_ANON_SUPPORT == ENABLED || TLS_ECDHE_RSA_SUPPORT == ENABLED || \
01270    TLS_ECDHE_ECDSA_SUPPORT == ENABLED || TLS_ECDHE_PSK_SUPPORT == ENABLED)
01271       //Release ECDH context
01272       ecdhFree(&context->ecdhContext);
01273 #endif
01274 
01275 #if (TLS_RSA_SIGN_SUPPORT == ENABLED || TLS_RSA_SUPPORT == ENABLED || \
01276    TLS_DHE_RSA_SUPPORT == ENABLED || TLS_ECDHE_RSA_SUPPORT == ENABLED)
01277       //Release peer's RSA public key
01278       rsaFreePublicKey(&context->peerRsaPublicKey);
01279 #endif
01280 
01281 #if (TLS_DSA_SIGN_SUPPORT == ENABLED || TLS_DHE_DSS_SUPPORT == ENABLED)
01282       //Release peer's DSA public key
01283       dsaFreePublicKey(&context->peerDsaPublicKey);
01284 #endif
01285 
01286 #if (TLS_ECDSA_SIGN_SUPPORT == ENABLED || TLS_ECDHE_ECDSA_SUPPORT == ENABLED)
01287       //Release peer's EC domain parameters
01288       ecFreeDomainParameters(&context->peerEcParams);
01289       //Release peer's EC public key
01290       ecFree(&context->peerEcPublicKey);
01291 #endif
01292 
01293       //Release send buffer
01294       if(context->txBuffer != NULL)
01295       {
01296          memset(context->txBuffer, 0, context->txBufferSize);
01297          tlsFreeMem(context->txBuffer);
01298       }
01299 
01300       //Release receive buffer
01301       if(context->rxBuffer != NULL)
01302       {
01303          memset(context->rxBuffer, 0, context->rxBufferSize);
01304          tlsFreeMem(context->rxBuffer);
01305       }
01306 
01307       //Release the MD5 context used to compute verify data
01308       if(context->handshakeMd5Context != NULL)
01309       {
01310          memset(context->handshakeMd5Context, 0, sizeof(Md5Context));
01311          tlsFreeMem(context->handshakeMd5Context);
01312       }
01313 
01314       //Release the SHA-1 context used to compute verify data
01315       if(context->handshakeSha1Context != NULL)
01316       {
01317          memset(context->handshakeSha1Context, 0, sizeof(Sha1Context));
01318          tlsFreeMem(context->handshakeSha1Context);
01319       }
01320 
01321       //Release the hash context used to compute verify data (TLS 1.2)
01322       if(context->handshakeHashContext != NULL)
01323       {
01324          memset(context->handshakeHashContext, 0, context->prfHashAlgo->contextSize);
01325          tlsFreeMem(context->handshakeHashContext);
01326       }
01327 
01328       //Release the encryption context (TX path)
01329       if(context->writeCipherContext != NULL)
01330       {
01331          memset(context->writeCipherContext, 0, context->cipherAlgo->contextSize);
01332          tlsFreeMem(context->writeCipherContext);
01333       }
01334 
01335       //Release the encryption context (RX path)
01336       if(context->readCipherContext != NULL)
01337       {
01338          memset(context->readCipherContext, 0, context->cipherAlgo->contextSize);
01339          tlsFreeMem(context->readCipherContext);
01340       }
01341 
01342 #if (TLS_GCM_CIPHER_SUPPORT == ENABLED)
01343       //Release the GCM context (TX path)
01344       if(context->writeGcmContext != NULL)
01345       {
01346          memset(context->writeGcmContext, 0, sizeof(GcmContext));
01347          tlsFreeMem(context->writeGcmContext);
01348       }
01349 
01350       //Release the GCM context (RX path)
01351       if(context->readGcmContext != NULL)
01352       {
01353          memset(context->readGcmContext, 0, sizeof(GcmContext));
01354          tlsFreeMem(context->readGcmContext);
01355       }
01356 #endif
01357 
01358       //Clear the TLS context before freeing memory
01359       memset(context, 0, sizeof(TlsContext));
01360       tlsFreeMem(context);
01361    }
01362 }
01363 
01364 
01365 /**
01366  * @brief Save TLS session
01367  * @param[in] context Pointer to the TLS context
01368  * @param[out] session Buffer where to store the current session parameters
01369  * @return Error code
01370  **/
01371 
01372 error_t tlsSaveSession(const TlsContext *context, TlsSession *session)
01373 {
01374    //Check parameters
01375    if(context == NULL || session == NULL)
01376       return ERROR_INVALID_PARAMETER;
01377 
01378    //Invalid session parameters?
01379    if(!context->sessionIdLen || !context->cipherSuite)
01380       return ERROR_FAILURE;
01381 
01382    //Save session identifier
01383    memcpy(session->id, context->sessionId, context->sessionIdLen);
01384    session->idLength = context->sessionIdLen;
01385 
01386    //Get current time
01387    session->timestamp = osGetSystemTime();
01388 
01389    //Negotiated cipher suite and compression method
01390    session->cipherSuite = context->cipherSuite;
01391    session->compressionMethod = context->compressionMethod;
01392 
01393    //Save master secret
01394    memcpy(session->masterSecret, context->masterSecret, 48);
01395 
01396    //Successful processing
01397    return NO_ERROR;
01398 }
01399 
01400 
01401 /**
01402  * @brief Restore TLS session
01403  * @param[in] context Pointer to the TLS context
01404  * @param[in] session Pointer to the session to be restored
01405  * @return Error code
01406  **/
01407 
01408 error_t tlsRestoreSession(TlsContext *context, const TlsSession *session)
01409 {
01410    //Check parameters
01411    if(context == NULL || session == NULL)
01412       return ERROR_INVALID_PARAMETER;
01413 
01414    //Restore session identifier
01415    memcpy(context->sessionId, session->id, session->idLength);
01416    context->sessionIdLen = session->idLength;
01417 
01418    //Negotiated cipher suite and compression method
01419    context->cipherSuite = session->cipherSuite;
01420    context->compressionMethod = session->compressionMethod;
01421 
01422    //Restore master secret
01423    memcpy(context->masterSecret, session->masterSecret, 48);
01424 
01425    //Successful processing
01426    return NO_ERROR;
01427 }
01428 
01429 #endif
01430