Sergey Pastor / 1

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers tls_misc.c Source File

tls_misc.c

Go to the documentation of this file.
00001 /**
00002  * @file tls_misc.c
00003  * @brief Helper functions (TLS client and server)
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_cipher_suites.h"
00036 #include "tls_common.h"
00037 #include "tls_record.h"
00038 #include "tls_misc.h"
00039 #include "ssl_common.h"
00040 #include "asn1.h"
00041 #include "oid.h"
00042 #include "x509.h"
00043 #include "pem.h"
00044 #include "debug.h"
00045 
00046 //Check SSL library configuration
00047 #if (TLS_SUPPORT == ENABLED)
00048 
00049 
00050 /**
00051  * @brief Translate an error code to an alert message
00052  * @param[in] context Pointer to the TLS context
00053  * @param[in] errorCode Internal error code
00054  * @return Error code
00055  **/
00056 
00057 void tlsProcessError(TlsContext *context, error_t errorCode)
00058 {
00059    //Check current state
00060    if(context->state != TLS_STATE_CLOSED)
00061    {
00062       //Check status code
00063       switch(errorCode)
00064       {
00065       //The timeout interval has elapsed
00066       case ERROR_TIMEOUT:
00067          break;
00068       //The read/write operation would have blocked
00069       case ERROR_WOULD_BLOCK:
00070          break;
00071       //The read/write operation has failed
00072       case ERROR_WRITE_FAILED:
00073       case ERROR_READ_FAILED:
00074          break;
00075       //An inappropriate message was received
00076       case ERROR_UNEXPECTED_MESSAGE:
00077          tlsSendAlert(context, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE);
00078          break;
00079       //A record is received with an incorrect MAC
00080       case ERROR_BAD_RECORD_MAC:
00081          tlsSendAlert(context, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_BAD_RECORD_MAC);
00082          break;
00083       //Invalid record length
00084       case ERROR_RECORD_OVERFLOW:
00085          tlsSendAlert(context, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_RECORD_OVERFLOW);
00086          break;
00087       //Unable to negotiate an acceptable set of security parameters
00088       case ERROR_HANDSHAKE_FAILED:
00089          tlsSendAlert(context, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_HANDSHAKE_FAILURE);
00090          break;
00091       //A certificate was corrupt
00092       case ERROR_BAD_CERTIFICATE:
00093          tlsSendAlert(context, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_BAD_CERTIFICATE);
00094          break;
00095       //A certificate was of an unsupported type
00096       case ERROR_UNSUPPORTED_CERTIFICATE:
00097          tlsSendAlert(context, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNSUPPORTED_CERTIFICATE);
00098          break;
00099       //A certificate has expired or is not currently valid
00100       case ERROR_CERTIFICATE_EXPIRED:
00101          tlsSendAlert(context, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_CERTIFICATE_EXPIRED);
00102          break;
00103       //A field in the handshake was out of range or inconsistent with other fields
00104       case ERROR_ILLEGAL_PARAMETER:
00105          tlsSendAlert(context, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_ILLEGAL_PARAMETER);
00106          break;
00107       //The certificate could not be matched with a known, trusted CA
00108       case ERROR_UNKNOWN_CA:
00109          tlsSendAlert(context, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNKNOWN_CA);
00110          break;
00111       //A message could not be decoded because some field was incorrect
00112       case ERROR_DECODING_FAILED:
00113          tlsSendAlert(context, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
00114          break;
00115       //A handshake cryptographic operation failed
00116       case ERROR_INVALID_SIGNATURE:
00117          tlsSendAlert(context, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECRYPT_ERROR);
00118          break;
00119       //The protocol version the client has attempted to negotiate is not supported
00120       case ERROR_VERSION_NOT_SUPPORTED:
00121          tlsSendAlert(context, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_PROTOCOL_VERSION);
00122          break;
00123       //Internal error
00124       default:
00125          tlsSendAlert(context, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR);
00126          break;
00127       }
00128    }
00129 }
00130 
00131 
00132 /**
00133  * @brief Generate client or server random value
00134  * @param[in] context Pointer to the TLS context
00135  * @param[out] random Pointer to the random value
00136  * @return Error code
00137  **/
00138 
00139 error_t tlsGenerateRandomValue(TlsContext *context, TlsRandom *random)
00140 {
00141    error_t error;
00142    uint32_t time;
00143 
00144    //Verify that the pseudorandom number generator is properly configured
00145    if(context->prngAlgo != NULL && context->prngContext != NULL)
00146    {
00147       //Get current time
00148       time = (uint32_t) getCurrentUnixTime();
00149 
00150       //Clocks are not required to be set correctly by the basic TLS protocol
00151       if(time != 0)
00152       {
00153          //Generate the random value. The first four bytes code the current
00154          //time and date in standard Unix format
00155          random->gmtUnixTime = htonl(time);
00156 
00157          //The last 28 bytes contain securely-generated random bytes
00158          error = context->prngAlgo->read(context->prngContext, random->randomBytes, 28);
00159       }
00160       else
00161       {
00162          //Generate a 32-byte random value using a cryptographically-safe
00163          //pseudorandom number generator
00164          error = context->prngAlgo->read(context->prngContext, (uint8_t *) random, 32);
00165       }
00166    }
00167    else
00168    {
00169       //Report an error
00170       error = ERROR_NOT_CONFIGURED;
00171    }
00172 
00173    //Return status code
00174    return error;
00175 }
00176 
00177 
00178 /**
00179  * @brief Set TLS version to use
00180  * @param[in] context Pointer to the TLS context
00181  * @param[in] version TLS version
00182  * @return Error code
00183  **/
00184 
00185 error_t tlsSetVersion(TlsContext *context, uint16_t version)
00186 {
00187    //Check TLS version
00188    if(version < TLS_MIN_VERSION || version > TLS_MAX_VERSION)
00189    {
00190       //Debug message
00191       TRACE_WARNING("TLS version not supported!\r\n");
00192       //Report an error
00193       return ERROR_VERSION_NOT_SUPPORTED;
00194    }
00195 
00196    //Save the TLS protocol version to use
00197    context->version = version;
00198    //Successful processing
00199    return NO_ERROR;
00200 }
00201 
00202 
00203 /**
00204  * @brief Set cipher suite
00205  * @param[in] context Pointer to the TLS context
00206  * @param[in] identifier Cipher suite identifier
00207  * @return Error code
00208  **/
00209 
00210 error_t tlsSetCipherSuite(TlsContext *context, uint16_t identifier)
00211 {
00212    error_t error;
00213    uint_t i;
00214    uint_t n;
00215    bool_t acceptable;
00216    const TlsCipherSuiteInfo *cipherSuite;
00217 
00218    //Initialize pointer
00219    cipherSuite = NULL;
00220 
00221    //Restrict the use of certain cipher suites?
00222    if(context->numCipherSuites > 0)
00223    {
00224       //This flag will be set if the specified cipher suite is acceptable
00225       acceptable = FALSE;
00226 
00227       //Loop through allowed cipher suites
00228       for(i = 0; i < context->numCipherSuites; i++)
00229       {
00230          //Compare cipher suite identifiers
00231          if(context->cipherSuites[i] == identifier)
00232          {
00233             acceptable = TRUE;
00234             break;
00235          }
00236       }
00237    }
00238    else
00239    {
00240       //The use of the cipher suite is not restricted
00241       acceptable = TRUE;
00242    }
00243 
00244    //No restrictions exist concerning the use of the specified cipher suite?
00245    if(acceptable)
00246    {
00247       //This flag will be set if the specified cipher suite is acceptable
00248       acceptable = FALSE;
00249 
00250       //Determine the number of supported cipher suites
00251       n = tlsGetNumSupportedCipherSuites();
00252 
00253       //Loop through the list of supported cipher suites
00254       for(i = 0; i < n; i++)
00255       {
00256          //Point to the current item
00257          cipherSuite = &tlsSupportedCipherSuites[i];
00258 
00259          //Compare cipher suite identifiers
00260          if(cipherSuite->identifier == identifier)
00261          {
00262             acceptable = TRUE;
00263             break;
00264          }
00265       }
00266    }
00267 
00268    //TLS 1.2 cipher suites must not be negotiated in older versions of TLS
00269    if(acceptable && context->version < TLS_VERSION_1_2)
00270    {
00271       if(cipherSuite->prfHashAlgo != NULL)
00272          acceptable = FALSE;
00273    }
00274 
00275    //Ensure that the selected cipher suite matches all the criteria
00276    if(acceptable)
00277    {
00278       //Save cipher suite identifier
00279       context->cipherSuite = identifier;
00280       //Set key exchange method
00281       context->keyExchMethod = cipherSuite->keyExchMethod;
00282 
00283       //Set encryption algorithm and hash function
00284       context->cipherAlgo = cipherSuite->cipherAlgo;
00285       context->cipherMode = cipherSuite->cipherMode;
00286       context->hashAlgo = cipherSuite->hashAlgo;
00287       context->prfHashAlgo = cipherSuite->prfHashAlgo;
00288 
00289       //Set appropriate length for MAC keys, encryption keys and IVs
00290       context->macKeyLen = cipherSuite->macKeyLen;
00291       context->encKeyLen = cipherSuite->encKeyLen;
00292       context->fixedIvLen = cipherSuite->fixedIvLen;
00293       context->recordIvLen = cipherSuite->recordIvLen;
00294 
00295       //Size of the authentication tag
00296       context->authTagLen = cipherSuite->authTagLen;
00297       //Size of the verify data
00298       context->verifyDataLen = cipherSuite->verifyDataLen;
00299 
00300       //PRF with the SHA-256 is used for all cipher suites published
00301       //prior than TLS 1.2 when TLS 1.2 is negotiated
00302       if(context->prfHashAlgo == NULL)
00303          context->prfHashAlgo = SHA256_HASH_ALGO;
00304 
00305       //The length of the verify data depends on the TLS version currently used
00306       if(context->version == SSL_VERSION_3_0)
00307          context->verifyDataLen = 36;
00308       else if(context->version <= TLS_VERSION_1_1)
00309          context->verifyDataLen = 12;
00310 
00311       //Successful processing
00312       error = NO_ERROR;
00313    }
00314    else
00315    {
00316       //Debug message
00317       TRACE_ERROR("Cipher suite not supported!\r\n");
00318       //The specified cipher suite is not supported
00319       error = ERROR_HANDSHAKE_FAILED;
00320    }
00321 
00322    //Return status code
00323    return error;
00324 }
00325 
00326 
00327 /**
00328  * @brief Set compression method
00329  * @param[in] context Pointer to the TLS context
00330  * @param[in] identifier Compression method identifier
00331  * @return Error code
00332  **/
00333 
00334 error_t tlsSetCompressionMethod(TlsContext *context, uint8_t identifier)
00335 {
00336    //Check if the requested compression algorithm is supported
00337    if(identifier != TLS_COMPRESSION_METHOD_NULL)
00338       return ERROR_HANDSHAKE_FAILED;
00339 
00340    //Save compression method identifier
00341    context->compressionMethod = identifier;
00342    //Successful processing
00343    return NO_ERROR;
00344 }
00345 
00346 
00347 /**
00348  * @brief Select the hash algorithm to be used when generating signatures
00349  * @param[in] context Pointer to the TLS context
00350  * @param[in] signAlgo Desired signature algorithm (RSA, DSA or ECDSA)
00351  * @param[in] supportedSignAlgos List of supported signature/hash algorithm pairs
00352  * @return Error code
00353  **/
00354 
00355 error_t tlsSelectSignHashAlgo(TlsContext *context,
00356    TlsSignatureAlgo signAlgo, const TlsSignHashAlgos *supportedSignAlgos)
00357 {
00358    uint_t i;
00359    uint_t n;
00360 
00361    //Check whether the peer has provided a list of supported
00362    //hash/signature algorithm pairs?
00363    if(supportedSignAlgos != NULL)
00364    {
00365       //Process the list and select the relevant hash algorithm...
00366       context->signHashAlgo = TLS_HASH_ALGO_NONE;
00367       //Get the number of hash/signature algorithm pairs present in the list
00368       n = ntohs(supportedSignAlgos->length) / sizeof(TlsSignHashAlgo);
00369 
00370       //The hash algorithm to be used when generating signatures must be
00371       //one of those present in the list
00372       for(i = 0; i < n; i++)
00373       {
00374          //Acceptable signature algorithm found?
00375          if(supportedSignAlgos->value[i].signature == signAlgo)
00376          {
00377             //TLS operates as a client?
00378             if(context->entity == TLS_CONNECTION_END_CLIENT)
00379             {
00380                //Check whether the associated hash algorithm is supported
00381                if(supportedSignAlgos->value[i].hash == TLS_HASH_ALGO_SHA1)
00382                   context->signHashAlgo = (TlsHashAlgo) supportedSignAlgos->value[i].hash;
00383                else if(tlsGetHashAlgo(supportedSignAlgos->value[i].hash) == context->prfHashAlgo)
00384                   context->signHashAlgo = (TlsHashAlgo) supportedSignAlgos->value[i].hash;
00385             }
00386             //TLS operates as a server?
00387             else
00388             {
00389                //Check whether the associated hash algorithm is supported
00390                switch(supportedSignAlgos->value[i].hash)
00391                {
00392                //MD5 hash identifier?
00393                case TLS_HASH_ALGO_MD5:
00394                //SHA-1 hash identifier?
00395                case TLS_HASH_ALGO_SHA1:
00396                //SHA-256 hash identifier?
00397                case TLS_HASH_ALGO_SHA256:
00398 #if (TLS_SHA224_SUPPORT == ENABLED)
00399                //SHA-224 hash identifier?
00400                case TLS_HASH_ALGO_SHA224:
00401 #endif
00402 #if (TLS_SHA384_SUPPORT == ENABLED)
00403                //SHA-384 hash identifier?
00404                case TLS_HASH_ALGO_SHA384:
00405 #endif
00406 #if (TLS_SHA512_SUPPORT == ENABLED)
00407                //SHA-512 hash identifier?
00408                case TLS_HASH_ALGO_SHA512:
00409 #endif
00410                   //Select the hash algorithm to be used for signing
00411                   context->signHashAlgo = (TlsHashAlgo) supportedSignAlgos->value[i].hash;
00412                   break;
00413                default:
00414                   break;
00415                }
00416             }
00417 
00418             //Acceptable hash algorithm found?
00419             if(context->signHashAlgo != TLS_HASH_ALGO_NONE)
00420                break;
00421          }
00422       }
00423    }
00424    else
00425    {
00426       //Use default hash algorithm when generating RSA, DSA or ECDSA signatures
00427       context->signHashAlgo = TLS_HASH_ALGO_SHA1;
00428    }
00429 
00430    //If no acceptable choices are presented, return an error
00431    if(context->signHashAlgo == TLS_HASH_ALGO_NONE)
00432       return ERROR_FAILURE;
00433 
00434    //Successful processing
00435    return NO_ERROR;
00436 }
00437 
00438 
00439 /**
00440  * @brief Select the named curve to be used when performing ECDH key exchange
00441  * @param[in] context Pointer to the TLS context
00442  * @param[in] curveList Set of elliptic curves supported by the peer
00443  * @return Error code
00444  **/
00445 
00446 error_t tlsSelectNamedCurve(TlsContext *context,
00447    const TlsEllipticCurveList *curveList)
00448 {
00449    uint_t i;
00450    uint_t n;
00451 
00452    //Check whether a list of elliptic curves has been provided
00453    if(curveList != NULL)
00454    {
00455       //Process the list and select the relevant elliptic curve...
00456       context->namedCurve = TLS_EC_CURVE_NONE;
00457       //Get the number of named curves present in the list
00458       n = ntohs(curveList->length) / sizeof(uint16_t);
00459 
00460       //The named curve to be used when performing ECDH key exchange must be
00461       //one of those present in the list
00462       for(i = 0; i < n; i++)
00463       {
00464          //Acceptable elliptic curve found?
00465          if(tlsGetCurveInfo(ntohs(curveList->value[i])) != NULL)
00466          {
00467             //Save the named curve
00468             context->namedCurve = ntohs(curveList->value[i]);
00469             //We are done
00470             break;
00471          }
00472       }
00473    }
00474    else
00475    {
00476       //No list provided
00477       context->namedCurve = TLS_EC_CURVE_NONE;
00478    }
00479 
00480    //If no acceptable choices are presented, return an error
00481    if(context->namedCurve == TLS_EC_CURVE_NONE)
00482       return ERROR_FAILURE;
00483 
00484    //Successful processing
00485    return NO_ERROR;
00486 }
00487 
00488 
00489 /**
00490  * @brief Initialize handshake message hashing
00491  * @param[in] context Pointer to the TLS context
00492  * @return Error code
00493  **/
00494 
00495 error_t tlsInitHandshakeHash(TlsContext *context)
00496 {
00497    //Allocate SHA-1 context
00498    context->handshakeSha1Context = tlsAllocMem(sizeof(Sha1Context));
00499    //Failed to allocate memory?
00500    if(context->handshakeSha1Context == NULL)
00501       return ERROR_OUT_OF_MEMORY;
00502 
00503    //Initialize SHA-1 context
00504    sha1Init(context->handshakeSha1Context);
00505 
00506    //SSL 3.0, TLS 1.0 or 1.1 currently selected?
00507    if(context->version <= TLS_VERSION_1_1)
00508    {
00509       //Allocate MD5 context
00510       context->handshakeMd5Context = tlsAllocMem(sizeof(Md5Context));
00511 
00512       //Failed to allocate memory?
00513       if(context->handshakeMd5Context == NULL)
00514       {
00515          //Clean up side effects
00516          tlsFreeMem(context->handshakeSha1Context);
00517          //Report an error
00518          return ERROR_OUT_OF_MEMORY;
00519       }
00520 
00521       //Initialize MD5 context
00522       md5Init(context->handshakeMd5Context);
00523    }
00524    //TLS 1.2 currently selected?
00525    else
00526    {
00527       //Allocate a memory buffer to hold the hash algorithm context
00528       context->handshakeHashContext = tlsAllocMem(context->prfHashAlgo->contextSize);
00529 
00530       //Failed to allocate memory?
00531       if(context->handshakeHashContext == NULL)
00532       {
00533          //Clean up side effects
00534          tlsFreeMem(context->handshakeSha1Context);
00535          //Report an error
00536          return ERROR_OUT_OF_MEMORY;
00537       }
00538 
00539       //Initialize the hash algorithm context
00540       context->prfHashAlgo->init(context->handshakeHashContext);
00541    }
00542 
00543 #if (TLS_CLIENT_SUPPORT == ENABLED)
00544    //TLS operates as a client?
00545    if(context->entity == TLS_CONNECTION_END_CLIENT)
00546    {
00547       size_t length;
00548       TlsHandshake *message;
00549 
00550       //Point to the ClientHello message
00551       message = (TlsHandshake *) (context->txBuffer + sizeof(TlsRecord));
00552       //Retrieve the length of the message
00553       length = LOAD24BE(message->length);
00554 
00555       //Sanity check
00556       if(length <= context->txRecordMaxLen)
00557       {
00558          //Update the hash value with ClientHello message contents
00559          tlsUpdateHandshakeHash(context, message, length + sizeof(TlsHandshake));
00560       }
00561    }
00562 #endif
00563 
00564    //Successful initialization
00565    return NO_ERROR;
00566 }
00567 
00568 
00569 /**
00570  * @brief Update hash value with a handshake message
00571  * @param[in] context Pointer to the TLS context
00572  * @param[in] data Pointer to the handshake message being hashed
00573  * @param[in] length Length of the message
00574  **/
00575 
00576 void tlsUpdateHandshakeHash(TlsContext *context, const void *data, size_t length)
00577 {
00578    //Update SHA-1 hash value with message contents
00579    if(context->handshakeSha1Context)
00580       sha1Update(context->handshakeSha1Context, data, length);
00581 
00582    //SSL 3.0, TLS 1.0 or 1.1 currently selected?
00583    if(context->version <= TLS_VERSION_1_1)
00584    {
00585       //Update MD5 hash value with message contents
00586       if(context->handshakeMd5Context)
00587          md5Update(context->handshakeMd5Context, data, length);
00588    }
00589    //TLS 1.2 currently selected?
00590    else
00591    {
00592       //Update hash value with message contents
00593       if(context->handshakeHashContext)
00594          context->prfHashAlgo->update(context->handshakeHashContext, data, length);
00595    }
00596 }
00597 
00598 
00599 /**
00600  * @brief Finalize hash calculation from previous handshake messages
00601  * @param[in] context Pointer to the TLS context
00602  * @param[in] hash Hash function used to digest the handshake messages
00603  * @param[in] hashContext Pointer to the hash context
00604  * @param[in] label NULL-terminated string
00605  * @param[out] output Buffer where to store the resulting hash value
00606  * @return Error code
00607  **/
00608 
00609 error_t tlsFinalizeHandshakeHash(TlsContext *context, const HashAlgo *hash,
00610    const void *hashContext, const char_t *label, uint8_t *output)
00611 {
00612    error_t error;
00613    HashContext *tempHashContext;
00614 
00615    //Check parameters
00616    if(!context || !hash || !hashContext || !label || !output)
00617       return ERROR_INVALID_PARAMETER;
00618 
00619    //Allocate a temporary hash context
00620    tempHashContext = tlsAllocMem(hash->contextSize);
00621    //Memory allocation failed?
00622    if(tempHashContext == NULL)
00623       return ERROR_OUT_OF_MEMORY;
00624 
00625    //Original hash context must be preserved
00626    memcpy(tempHashContext, hashContext, hash->contextSize);
00627 
00628 #if (TLS_MAX_VERSION >= SSL_VERSION_3_0 && TLS_MIN_VERSION <= SSL_VERSION_3_0)
00629    //SSL 3.0 currently selected?
00630    if(context->version == SSL_VERSION_3_0)
00631    {
00632       size_t labelLength;
00633       size_t padLength;
00634 
00635       //Compute the length of the label
00636       labelLength = strlen(label);
00637 
00638       //The pad character is repeated 48 times for MD5 or 40 times for SHA-1
00639       padLength = (hash == MD5_HASH_ALGO) ? 48 : 40;
00640 
00641       //hash(handshakeMessages + label + masterSecret + pad1)
00642       hash->update(tempHashContext, label, labelLength);
00643       hash->update(tempHashContext, context->masterSecret, 48);
00644       hash->update(tempHashContext, sslPad1, padLength);
00645       hash->final(tempHashContext, output);
00646 
00647       //hash(masterSecret + pad2 + hash(handshakeMessages + label + masterSecret + pad1))
00648       hash->init(tempHashContext);
00649       hash->update(tempHashContext, context->masterSecret, 48);
00650       hash->update(tempHashContext, sslPad2, padLength);
00651       hash->update(tempHashContext, output, hash->digestSize);
00652       hash->final(tempHashContext, output);
00653 
00654       //Successful processing
00655       error = NO_ERROR;
00656    }
00657    else
00658 #endif
00659 #if (TLS_MAX_VERSION >= TLS_VERSION_1_0 && TLS_MIN_VERSION <= TLS_VERSION_1_2)
00660    //TLS 1.0, TLS 1.1 or TLS 1.2 currently selected?
00661    if(context->version >= TLS_VERSION_1_0 && context->version <= TLS_VERSION_1_2)
00662    {
00663       //Compute hash(handshakeMessages)
00664       hash->final(tempHashContext, output);
00665       //Successful processing
00666       error = NO_ERROR;
00667    }
00668    else
00669 #endif
00670    //The negotiated TLS version is not valid...
00671    {
00672       //Report an error
00673       error = ERROR_INVALID_VERSION;
00674    }
00675 
00676    //Release previously allocated resources
00677    tlsFreeMem(tempHashContext);
00678    //Return status code
00679    return error;
00680 }
00681 
00682 
00683 /**
00684  * @brief Compute verify data from previous handshake messages
00685  * @param[in] context Pointer to the TLS context
00686  * @param[in] entity Specifies whether the computation is performed at client or server side
00687  * @return Error code
00688  **/
00689 
00690 error_t tlsComputeVerifyData(TlsContext *context, TlsConnectionEnd entity)
00691 {
00692    error_t error;
00693    const char_t *label;
00694 
00695 #if (TLS_MAX_VERSION >= SSL_VERSION_3_0 && TLS_MIN_VERSION <= SSL_VERSION_3_0)
00696    //SSL 3.0 currently selected?
00697    if(context->version == SSL_VERSION_3_0)
00698    {
00699       //Computation is performed at client or server side?
00700       label = (entity == TLS_CONNECTION_END_CLIENT) ? "CLNT" : "SRVR";
00701 
00702       //Compute MD5(masterSecret + pad2 + MD5(handshakeMessages + label + masterSecret + pad1))
00703       error = tlsFinalizeHandshakeHash(context, MD5_HASH_ALGO,
00704          context->handshakeMd5Context, label, context->verifyData);
00705       //Any error to report?
00706       if(error)
00707          return error;
00708 
00709       //Compute SHA(masterSecret + pad2 + SHA(handshakeMessages + label + masterSecret + pad1))
00710       error = tlsFinalizeHandshakeHash(context, SHA1_HASH_ALGO,
00711          context->handshakeSha1Context, label, context->verifyData + MD5_DIGEST_SIZE);
00712       //Any error to report?
00713       if(error)
00714          return error;
00715    }
00716    else
00717 #endif
00718 #if (TLS_MAX_VERSION >= TLS_VERSION_1_0 && TLS_MIN_VERSION <= TLS_VERSION_1_1)
00719    //TLS 1.0 or 1.1 currently selected?
00720    if(context->version == TLS_VERSION_1_0 || context->version == TLS_VERSION_1_1)
00721    {
00722       //A temporary buffer is needed to concatenate MD5
00723       //and SHA-1 hash values before computing PRF
00724       uint8_t buffer[MD5_DIGEST_SIZE + SHA1_DIGEST_SIZE];
00725 
00726       //Finalize MD5 hash computation
00727       error = tlsFinalizeHandshakeHash(context, MD5_HASH_ALGO,
00728          context->handshakeMd5Context, "", buffer);
00729       //Any error to report?
00730       if(error)
00731          return error;
00732 
00733       //Finalize SHA-1 hash computation
00734       error = tlsFinalizeHandshakeHash(context, SHA1_HASH_ALGO,
00735          context->handshakeSha1Context, "", buffer + MD5_DIGEST_SIZE);
00736       //Any error to report?
00737       if(error)
00738          return error;
00739 
00740       //Computation is performed at client or server side?
00741       label = (entity == TLS_CONNECTION_END_CLIENT) ? "client finished" : "server finished";
00742 
00743       //Verify data is always 12-byte long for TLS 1.0 and 1.1
00744       error = tlsPrf(context->masterSecret, 48, label, buffer,
00745          MD5_DIGEST_SIZE + SHA1_DIGEST_SIZE, context->verifyData, 12);
00746       //Any error to report?
00747       if(error)
00748          return error;
00749    }
00750    else
00751 #endif
00752 #if (TLS_MAX_VERSION >= TLS_VERSION_1_2 && TLS_MIN_VERSION <= TLS_VERSION_1_2)
00753    //TLS 1.2 currently selected?
00754    if(context->version == TLS_VERSION_1_2)
00755    {
00756       //Allocate a memory buffer to hold the hash algorithm context
00757       HashContext *hashContext = tlsAllocMem(context->prfHashAlgo->contextSize);
00758       //Failed to allocate memory?
00759       if(hashContext == NULL)
00760          return ERROR_OUT_OF_MEMORY;
00761 
00762       //The original hash context must be preserved
00763       memcpy(hashContext, context->handshakeHashContext, context->prfHashAlgo->contextSize);
00764       //Finalize hash computation
00765       context->prfHashAlgo->final(hashContext, NULL);
00766 
00767       //Computation is performed at client or server side?
00768       label = (entity == TLS_CONNECTION_END_CLIENT) ? "client finished" : "server finished";
00769 
00770       //Generate the verify data
00771       error = tlsPrf2(context->prfHashAlgo, context->masterSecret, 48, label, hashContext->digest,
00772          context->prfHashAlgo->digestSize, context->verifyData, context->verifyDataLen);
00773 
00774       //Release previously allocated memory
00775       tlsFreeMem(hashContext);
00776 
00777       //Any error to report?
00778       if(error)
00779          return error;
00780    }
00781    else
00782 #endif
00783    //The negotiated TLS version is not valid...
00784    {
00785       //Report an error
00786       return ERROR_INVALID_VERSION;
00787    }
00788 
00789    //Debug message
00790    TRACE_DEBUG("Verify data:\r\n");
00791    TRACE_DEBUG_ARRAY("  ", context->verifyData, context->verifyDataLen);
00792 
00793    //Successful processing
00794    return NO_ERROR;
00795 }
00796 
00797 
00798 /**
00799  * @brief Initialize encryption engine
00800  * @param[in] context Pointer to the TLS context
00801  * @return Error code
00802  **/
00803 
00804 error_t tlsInitEncryptionEngine(TlsContext *context)
00805 {
00806    error_t error;
00807 
00808    //Check cipher mode of operation
00809    if(context->cipherMode == CIPHER_MODE_STREAM ||
00810       context->cipherMode == CIPHER_MODE_CBC ||
00811       context->cipherMode == CIPHER_MODE_CCM ||
00812       context->cipherMode == CIPHER_MODE_GCM)
00813    {
00814       //Sanity check
00815       if(context->cipherAlgo != NULL)
00816       {
00817          //Allocate a memory buffer to hold the encryption context
00818          context->writeCipherContext = tlsAllocMem(context->cipherAlgo->contextSize);
00819 
00820          //Successful memory allocation?
00821          if(context->writeCipherContext != NULL)
00822          {
00823             //Configure the encryption engine with the write key
00824             error = context->cipherAlgo->init(context->writeCipherContext,
00825                context->writeEncKey, context->encKeyLen);
00826          }
00827          else
00828          {
00829             //Failed to allocate memory
00830             error = ERROR_OUT_OF_MEMORY;
00831          }
00832       }
00833       else
00834       {
00835          //Report an error
00836          error = ERROR_FAILURE;
00837       }
00838 
00839 #if (TLS_GCM_CIPHER_SUPPORT == ENABLED)
00840       //GCM AEAD cipher?
00841       if(context->cipherMode == CIPHER_MODE_GCM)
00842       {
00843          //Check status code
00844          if(!error)
00845          {
00846             //Allocate a memory buffer to hold the GCM context
00847             context->writeGcmContext = tlsAllocMem(sizeof(GcmContext));
00848 
00849             //Successful memory allocation?
00850             if(context->writeGcmContext != NULL)
00851             {
00852                //Initialize GCM context
00853                error = gcmInit(context->writeGcmContext,
00854                   context->cipherAlgo, context->writeCipherContext);
00855             }
00856             else
00857             {
00858                //Failed to allocate memory
00859                error = ERROR_OUT_OF_MEMORY;
00860             }
00861          }
00862       }
00863 #endif
00864    }
00865    else if(context->cipherMode == CIPHER_MODE_CHACHA20_POLY1305)
00866    {
00867       //We are done
00868       error = NO_ERROR;
00869    }
00870    else
00871    {
00872       //Unsupported mode of operation
00873       error = ERROR_FAILURE;
00874    }
00875 
00876    //Return status code
00877    return error;
00878 }
00879 
00880 
00881 /**
00882  * @brief Initialize decryption engine
00883  * @param[in] context Pointer to the TLS context
00884  * @return Error code
00885  **/
00886 
00887 error_t tlsInitDecryptionEngine(TlsContext *context)
00888 {
00889    error_t error;
00890 
00891    //Check cipher mode of operation
00892    if(context->cipherMode == CIPHER_MODE_STREAM ||
00893       context->cipherMode == CIPHER_MODE_CBC ||
00894       context->cipherMode == CIPHER_MODE_CCM ||
00895       context->cipherMode == CIPHER_MODE_GCM)
00896    {
00897       //Sanity check
00898       if(context->cipherAlgo != NULL)
00899       {
00900          //Allocate a memory buffer to hold the decryption context
00901          context->readCipherContext = tlsAllocMem(context->cipherAlgo->contextSize);
00902 
00903          //Successful memory allocation?
00904          if(context->readCipherContext != NULL)
00905          {
00906             //Configure the decryption engine with the read key
00907             error = context->cipherAlgo->init(context->readCipherContext,
00908                context->readEncKey, context->encKeyLen);
00909          }
00910          else
00911          {
00912             //Failed to allocate memory
00913             error = ERROR_OUT_OF_MEMORY;
00914          }
00915       }
00916       else
00917       {
00918          //Report an error
00919          error = ERROR_FAILURE;
00920       }
00921 
00922 #if (TLS_GCM_CIPHER_SUPPORT == ENABLED)
00923       //GCM AEAD cipher?
00924       if(context->cipherMode == CIPHER_MODE_GCM)
00925       {
00926          //Check status code
00927          if(!error)
00928          {
00929             //Allocate a memory buffer to hold the GCM context
00930             context->readGcmContext = tlsAllocMem(sizeof(GcmContext));
00931 
00932             //Successful memory allocation?
00933             if(context->readGcmContext != NULL)
00934             {
00935                //Initialize GCM context
00936                error = gcmInit(context->readGcmContext,
00937                   context->cipherAlgo, context->readCipherContext);
00938             }
00939             else
00940             {
00941                //Failed to allocate memory
00942                error = ERROR_OUT_OF_MEMORY;
00943             }
00944          }
00945       }
00946 #endif
00947    }
00948    else if(context->cipherMode == CIPHER_MODE_CHACHA20_POLY1305)
00949    {
00950       //We are done
00951       error = NO_ERROR;
00952    }
00953    else
00954    {
00955       //Unsupported mode of operation
00956       error = ERROR_FAILURE;
00957    }
00958 
00959    //Return status code
00960    return error;
00961 }
00962 
00963 
00964 /**
00965  * @brief Encode a multiple precision integer to an opaque vector
00966  * @param[in] a Pointer to a multiple precision integer
00967  * @param[out] data Buffer where to store the opaque vector
00968  * @param[out] length Total number of bytes that have been written
00969  * @return Error code
00970  **/
00971 
00972 error_t tlsWriteMpi(const Mpi *a, uint8_t *data, size_t *length)
00973 {
00974    error_t error;
00975    size_t n;
00976 
00977    //Retrieve the actual size of the integer
00978    n = mpiGetByteLength(a);
00979 
00980    //The data is preceded by a 2-byte length field
00981    STORE16BE(n, data);
00982 
00983    //Convert the integer to an octet string
00984    error = mpiWriteRaw(a, data + 2, n);
00985    //Conversion failed?
00986    if(error)
00987       return error;
00988 
00989    //Return the total number of bytes that have been written
00990    *length = n + 2;
00991    //Successful processing
00992    return NO_ERROR;
00993 }
00994 
00995 
00996 /**
00997  * @brief Read a multiple precision integer from an opaque vector
00998  * @param[out] a Resulting multiple precision integer
00999  * @param[in] data Buffer where to read the opaque vector
01000  * @param[in] size Total number of bytes available in the buffer
01001  * @param[out] length Total number of bytes that have been read
01002  * @return Error code
01003  **/
01004 
01005 error_t tlsReadMpi(Mpi *a, const uint8_t *data, size_t size, size_t *length)
01006 {
01007    error_t error;
01008    size_t n;
01009 
01010    //Buffer underrun?
01011    if(size < 2)
01012       return ERROR_DECODING_FAILED;
01013 
01014    //Decode the length field
01015    n = LOAD16BE(data);
01016 
01017    //Buffer underrun?
01018    if(size < (n + 2))
01019       return ERROR_DECODING_FAILED;
01020 
01021    //Convert the octet string to a multiple precision integer
01022    error = mpiReadRaw(a, data + 2, n);
01023    //Any error to report?
01024    if(error)
01025       return error;
01026 
01027    //Return the total number of bytes that have been read
01028    *length = n + 2;
01029    //Successful processing
01030    return NO_ERROR;
01031 }
01032 
01033 
01034 /**
01035  * @brief Encode an EC point to an opaque vector
01036  * @param[in] params EC domain parameters
01037  * @param[in] a Pointer to an EC point
01038  * @param[out] data Buffer where to store the opaque vector
01039  * @param[out] length Total number of bytes that have been written
01040  * @return Error code
01041  **/
01042 
01043 error_t tlsWriteEcPoint(const EcDomainParameters *params,
01044    const EcPoint *a, uint8_t *data, size_t *length)
01045 {
01046 #if (TLS_ECDH_ANON_SUPPORT == ENABLED || TLS_ECDHE_RSA_SUPPORT == ENABLED || \
01047    TLS_ECDHE_ECDSA_SUPPORT == ENABLED || TLS_ECDHE_PSK_SUPPORT == ENABLED)
01048    error_t error;
01049 
01050    //Convert the EC point to an octet string
01051    error = ecExport(params, a, data + 1, length);
01052    //Any error to report?
01053    if(error)
01054       return error;
01055 
01056    //Set the length of the opaque vector
01057    data[0] = (uint8_t) (*length);
01058 
01059    //Return the total number of bytes that have been written
01060    *length += 1;
01061    //Successful processing
01062    return NO_ERROR;
01063 #else
01064    //Not implemented
01065    return ERROR_NOT_IMPLEMENTED;
01066 #endif
01067 }
01068 
01069 
01070 /**
01071  * @brief Read an EC point from an opaque vector
01072  * @param[in] params EC domain parameters
01073  * @param[out] a Resulting EC point
01074  * @param[in] data Buffer where to read the opaque vector
01075  * @param[in] size Total number of bytes available in the buffer
01076  * @param[out] length Total number of bytes that have been read
01077  * @return Error code
01078  **/
01079 
01080 error_t tlsReadEcPoint(const EcDomainParameters *params,
01081    EcPoint *a, const uint8_t *data, size_t size, size_t *length)
01082 {
01083 #if (TLS_ECDH_ANON_SUPPORT == ENABLED || TLS_ECDHE_RSA_SUPPORT == ENABLED || \
01084    TLS_ECDHE_ECDSA_SUPPORT == ENABLED || TLS_ECDHE_PSK_SUPPORT == ENABLED)
01085    error_t error;
01086    size_t n;
01087 
01088    //Buffer underrun?
01089    if(size < 1)
01090       return ERROR_DECODING_FAILED;
01091 
01092    //The EC point representation is preceded by a length field
01093    n = data[0];
01094 
01095    //Valid EC point representation?
01096    if(size < (n + 1))
01097       return ERROR_DECODING_FAILED;
01098 
01099    //Convert the octet string to an EC point
01100    error = ecImport(params, a, data + 1, n);
01101    //Any error to report?
01102    if(error)
01103       return error;
01104 
01105    //Return the total number of bytes that have been read
01106    *length = n + 1;
01107    //Successful processing
01108    return NO_ERROR;
01109 #else
01110    //Not implemented
01111    return ERROR_NOT_IMPLEMENTED;
01112 #endif
01113 }
01114 
01115 
01116 /**
01117  * @brief Generate RSA signature (SSL 3.0, TLS 1.0 and TLS 1.1)
01118  * @param[in] key Signer's RSA private key
01119  * @param[in] digest Digest of the message to be signed
01120  * @param[out] signature Resulting signature
01121  * @param[out] signatureLength Length of the resulting signature
01122  * @return Error code
01123  **/
01124 
01125 error_t tlsGenerateRsaSignature(const RsaPrivateKey *key,
01126    const uint8_t *digest, uint8_t *signature, size_t *signatureLength)
01127 {
01128 #if (TLS_RSA_SIGN_SUPPORT == ENABLED || TLS_DHE_RSA_SUPPORT == ENABLED || TLS_ECDHE_RSA_SUPPORT == ENABLED)
01129    error_t error;
01130    size_t k;
01131    size_t paddingLength;
01132    uint8_t *em;
01133    Mpi m;
01134    Mpi s;
01135 
01136    //Debug message
01137    TRACE_DEBUG("RSA signature generation...\r\n");
01138    TRACE_DEBUG("  Modulus:\r\n");
01139    TRACE_DEBUG_MPI("    ", &key->n);
01140    TRACE_DEBUG("  Public exponent:\r\n");
01141    TRACE_DEBUG_MPI("    ", &key->e);
01142    TRACE_DEBUG("  Private exponent:\r\n");
01143    TRACE_DEBUG_MPI("    ", &key->d);
01144    TRACE_DEBUG("  Prime 1:\r\n");
01145    TRACE_DEBUG_MPI("    ", &key->p);
01146    TRACE_DEBUG("  Prime 2:\r\n");
01147    TRACE_DEBUG_MPI("    ", &key->q);
01148    TRACE_DEBUG("  Prime exponent 1:\r\n");
01149    TRACE_DEBUG_MPI("    ", &key->dp);
01150    TRACE_DEBUG("  Prime exponent 2:\r\n");
01151    TRACE_DEBUG_MPI("    ", &key->dq);
01152    TRACE_DEBUG("  Coefficient:\r\n");
01153    TRACE_DEBUG_MPI("    ", &key->qinv);
01154    TRACE_DEBUG("  Message digest:\r\n");
01155    TRACE_DEBUG_ARRAY("    ", digest, MD5_DIGEST_SIZE + SHA1_DIGEST_SIZE);
01156 
01157    //Initialize multiple-precision integers
01158    mpiInit(&m);
01159    mpiInit(&s);
01160 
01161    //Get the length in octets of the modulus n
01162    k = mpiGetByteLength(&key->n);
01163 
01164    //Check the length of the modulus
01165    if(k < (MD5_DIGEST_SIZE + SHA1_DIGEST_SIZE + 11))
01166       return ERROR_INVALID_KEY;
01167 
01168    //Point to the buffer where the encoded message EM will be generated
01169    em = signature;
01170 
01171    //The leading 0x00 octet ensures that the encoded message,
01172    //converted to an integer, is less than the modulus
01173    em[0] = 0x00;
01174    //Block type 0x01 is used for private-key operations
01175    em[1] = 0x01;
01176 
01177    //Compute the length of the padding string PS
01178    paddingLength = k - (MD5_DIGEST_SIZE + SHA1_DIGEST_SIZE + 3);
01179    //Fill the padding string with 0xFF
01180    memset(em + 2, 0xFF, paddingLength);
01181    //Append a 0x00 octet to PS
01182    em[paddingLength + 2] = 0x00;
01183 
01184    //Append the digest value
01185    memcpy(em + paddingLength + 3, digest, MD5_DIGEST_SIZE + SHA1_DIGEST_SIZE);
01186 
01187    //Debug message
01188    TRACE_DEBUG("  Encoded message\r\n");
01189    TRACE_DEBUG_ARRAY("    ", em, k);
01190 
01191    //Start of exception handling block
01192    do
01193    {
01194       //Convert the encoded message EM to an integer message representative m
01195       error = mpiReadRaw(&m, em, k);
01196       //Conversion failed?
01197       if(error)
01198          break;
01199 
01200       //Apply the RSASP1 signature primitive
01201       error = rsasp1(key, &m, &s);
01202       //Any error to report?
01203       if(error)
01204          break;
01205 
01206       //Convert the signature representative s to a signature of length k octets
01207       error = mpiWriteRaw(&s, signature, k);
01208       //Conversion failed?
01209       if(error)
01210          break;
01211 
01212       //Length of the resulting signature
01213       *signatureLength = k;
01214 
01215       //Debug message
01216       TRACE_DEBUG("  Signature:\r\n");
01217       TRACE_DEBUG_ARRAY("    ", signature, *signatureLength);
01218 
01219       //End of exception handling block
01220    } while(0);
01221 
01222    //Free previously allocated memory
01223    mpiFree(&m);
01224    mpiFree(&s);
01225 
01226    //Return status code
01227    return error;
01228 #else
01229    //Not implemented
01230    return ERROR_NOT_IMPLEMENTED;
01231 #endif
01232 }
01233 
01234 
01235 /**
01236  * @brief Verify RSA signature (SSL 3.0, TLS 1.0 and TLS 1.1)
01237  * @param[in] key Signer's RSA public key
01238  * @param[in] digest Digest of the message whose signature is to be verified
01239  * @param[in] signature Signature to be verified
01240  * @param[in] signatureLength Length of the signature to be verified
01241  * @return Error code
01242  **/
01243 
01244 error_t tlsVerifyRsaSignature(const RsaPublicKey *key,
01245    const uint8_t *digest, const uint8_t *signature, size_t signatureLength)
01246 {
01247 #if (TLS_RSA_SIGN_SUPPORT == ENABLED || TLS_DHE_RSA_SUPPORT == ENABLED || TLS_ECDHE_RSA_SUPPORT == ENABLED)
01248    error_t error;
01249    uint_t i;
01250    uint_t k;
01251    uint8_t *em;
01252    Mpi s;
01253    Mpi m;
01254 
01255    //Debug message
01256    TRACE_DEBUG("RSA signature verification...\r\n");
01257    TRACE_DEBUG("  Modulus:\r\n");
01258    TRACE_DEBUG_MPI("    ", &key->n);
01259    TRACE_DEBUG("  Public exponent:\r\n");
01260    TRACE_DEBUG_MPI("    ", &key->e);
01261    TRACE_DEBUG("  Message digest:\r\n");
01262    TRACE_DEBUG_ARRAY("    ", digest, MD5_DIGEST_SIZE + SHA1_DIGEST_SIZE);
01263    TRACE_DEBUG("  Signature:\r\n");
01264    TRACE_DEBUG_ARRAY("    ", signature, signatureLength);
01265 
01266    //Get the length in octets of the modulus n
01267    k = mpiGetByteLength(&key->n);
01268 
01269    //Check the length of the signature
01270    if(signatureLength != k)
01271       return ERROR_INVALID_SIGNATURE;
01272 
01273    //Initialize multiple-precision integers
01274    mpiInit(&s);
01275    mpiInit(&m);
01276 
01277    //Allocate a memory buffer to hold the encoded message
01278    em = tlsAllocMem(k);
01279    //Failed to allocate memory?
01280    if(em == NULL)
01281       return ERROR_OUT_OF_MEMORY;
01282 
01283    //Start of exception handling block
01284    do
01285    {
01286       //Convert the signature to an integer signature representative s
01287       error = mpiReadRaw(&s, signature, signatureLength);
01288       //Conversion failed?
01289       if(error)
01290          break;
01291 
01292       //Apply the RSAVP1 verification primitive
01293       error = rsavp1(key, &s, &m);
01294       //Any error to report?
01295       if(error)
01296          break;
01297 
01298       //Convert the message representative m to an encoded message EM of length k octets
01299       error = mpiWriteRaw(&m, em, k);
01300       //Conversion failed?
01301       if(error)
01302          break;
01303 
01304       //Debug message
01305       TRACE_DEBUG("  Encoded message\r\n");
01306       TRACE_DEBUG_ARRAY("    ", em, k);
01307 
01308       //Assume an error...
01309       error = ERROR_INVALID_SIGNATURE;
01310 
01311       //The first octet of EM must have a value of 0x00
01312       if(em[0] != 0x00)
01313          break;
01314       //The block type BT shall be 0x01
01315       if(em[1] != 0x01)
01316          break;
01317 
01318       //Check the padding string PS
01319       for(i = 2; i < k; i++)
01320       {
01321          //A 0x00 octet indicates the end of the padding string
01322          if(em[i] == 0x00)
01323             break;
01324 
01325          //Each byte of PS must be set to 0xFF when the block type is 0x01
01326          if(em[i] != 0xFF)
01327             break;
01328       }
01329 
01330       //Check whether the padding string is properly terminated
01331       if(i >= k || em[i] != 0x00)
01332          break;
01333 
01334       //The length of PS cannot be less than 8 octets
01335       if(i < 10)
01336          break;
01337 
01338       //Check the length of the digest
01339       if((k - i - 1) != (MD5_DIGEST_SIZE + SHA1_DIGEST_SIZE))
01340          break;
01341       //Check the digest value
01342       if(memcmp(digest, em + i + 1, MD5_DIGEST_SIZE + SHA1_DIGEST_SIZE))
01343          break;
01344 
01345       //The RSA signature is valid
01346       error = NO_ERROR;
01347 
01348       //End of exception handling block
01349    } while(0);
01350 
01351    //Release multiple precision integers
01352    mpiFree(&s);
01353    mpiFree(&m);
01354    //Release previously allocated memory
01355    tlsFreeMem(em);
01356 
01357    //Return status code
01358    return error;
01359 #else
01360    //Not implemented
01361    return ERROR_NOT_IMPLEMENTED;
01362 #endif
01363 }
01364 
01365 
01366 /**
01367  * @brief Generate DSA signature
01368  * @param[in] prngAlgo PRNG algorithm
01369  * @param[in] prngContext Pointer to the PRNG context
01370  * @param[in] key Signer's DSA private key
01371  * @param[in] digest Digest of the message to be signed
01372  * @param[in] digestLength Length in octets of the digest
01373  * @param[out] signature Resulting signature
01374  * @param[out] signatureLength Length of the resulting signature
01375  * @return Error code
01376  **/
01377 
01378 error_t tlsGenerateDsaSignature(const PrngAlgo *prngAlgo, void *prngContext, const DsaPrivateKey *key,
01379    const uint8_t *digest, size_t digestLength, uint8_t *signature, size_t *signatureLength)
01380 {
01381 #if (TLS_DSA_SIGN_SUPPORT == ENABLED || TLS_DHE_DSS_SUPPORT == ENABLED)
01382    error_t error;
01383    DsaSignature dsaSignature;
01384 
01385    //Initialize DSA signature
01386    dsaInitSignature(&dsaSignature);
01387 
01388    //Generate DSA signature
01389    error = dsaGenerateSignature(prngAlgo, prngContext,
01390       key, digest, digestLength, &dsaSignature);
01391    //Failed to generate signature?
01392    if(error)
01393       return error;
01394 
01395    //Encode the resulting (R, S) integer pair using ASN.1
01396    error = dsaWriteSignature(&dsaSignature, signature, signatureLength);
01397 
01398    //Free previously allocated resources
01399    dsaFreeSignature(&dsaSignature);
01400 
01401    //Return status code
01402    return error;
01403 #else
01404    //Not implemented
01405    return ERROR_NOT_IMPLEMENTED;
01406 #endif
01407 }
01408 
01409 
01410 /**
01411  * @brief Verify DSA signature
01412  * @param[in] key Signer's DSA public key
01413  * @param[in] digest Digest of the message whose signature is to be verified
01414  * @param[in] digestLength Length in octets of the digest
01415  * @param[in] signature Signature to be verified
01416  * @param[in] signatureLength Length of the signature to be verified
01417  * @return Error code
01418  **/
01419 
01420 error_t tlsVerifyDsaSignature(const DsaPublicKey *key, const uint8_t *digest,
01421    size_t digestLength, const uint8_t *signature, size_t signatureLength)
01422 {
01423 #if (TLS_DSA_SIGN_SUPPORT == ENABLED || TLS_DHE_DSS_SUPPORT == ENABLED)
01424    error_t error;
01425    DsaSignature dsaSignature;
01426 
01427    //Initialize DSA signature
01428    dsaInitSignature(&dsaSignature);
01429 
01430    //Read the ASN.1 encoded DSA signature
01431    error = dsaReadSignature(signature, signatureLength, &dsaSignature);
01432    //Failed to decode ASN.1 structure?
01433    if(error)
01434       return error;
01435 
01436    //DSA signature verification
01437    error = dsaVerifySignature(key, digest, digestLength, &dsaSignature);
01438 
01439    //Free previously allocated resources
01440    dsaFreeSignature(&dsaSignature);
01441 
01442    //Return status code
01443    return error;
01444 #else
01445    //Not implemented
01446    return ERROR_NOT_IMPLEMENTED;
01447 #endif
01448 }
01449 
01450 
01451 /**
01452  * @brief Generate ECDSA signature
01453  * @param[in] params EC domain parameters
01454  * @param[in] prngAlgo PRNG algorithm
01455  * @param[in] prngContext Pointer to the PRNG context
01456  * @param[in] key Signer's ECDSA private key
01457  * @param[in] digest Digest of the message to be signed
01458  * @param[in] digestLength Length in octets of the digest
01459  * @param[out] signature Resulting signature
01460  * @param[out] signatureLength Length of the resulting signature
01461  * @return Error code
01462  **/
01463 
01464 error_t tlsGenerateEcdsaSignature(const EcDomainParameters *params,
01465    const PrngAlgo *prngAlgo, void *prngContext, const Mpi *key, const uint8_t *digest,
01466    size_t digestLength, uint8_t *signature, size_t *signatureLength)
01467 {
01468 #if (TLS_ECDSA_SIGN_SUPPORT == ENABLED || TLS_ECDHE_ECDSA_SUPPORT == ENABLED)
01469    error_t error;
01470    EcdsaSignature ecdsaSignature;
01471 
01472    //Initialize ECDSA signature
01473    ecdsaInitSignature(&ecdsaSignature);
01474 
01475    //Generate ECDSA signature
01476    error = ecdsaGenerateSignature(params, prngAlgo,
01477       prngContext, key, digest, digestLength, &ecdsaSignature);
01478    //Failed to generate signature?
01479    if(error)
01480       return error;
01481 
01482    //Encode the resulting (R, S) integer pair using ASN.1
01483    error = ecdsaWriteSignature(&ecdsaSignature, signature, signatureLength);
01484 
01485    //Free previously allocated resources
01486    ecdsaFreeSignature(&ecdsaSignature);
01487 
01488    //Return status code
01489    return error;
01490 #else
01491    //Not implemented
01492    return ERROR_NOT_IMPLEMENTED;
01493 #endif
01494 }
01495 
01496 
01497 /**
01498  * @brief Verify ECDSA signature
01499  * @param[in] params EC domain parameters
01500  * @param[in] key Signer's ECDSA public key
01501  * @param[in] digest Digest of the message whose signature is to be verified
01502  * @param[in] digestLength Length in octets of the digest
01503  * @param[in] signature Signature to be verified
01504  * @param[in] signatureLength Length of the signature to be verified
01505  * @return Error code
01506  **/
01507 
01508 error_t tlsVerifyEcdsaSignature(const EcDomainParameters *params,
01509    const EcPoint *key, const uint8_t *digest, size_t digestLength,
01510    const uint8_t *signature, size_t signatureLength)
01511 {
01512 #if (TLS_ECDSA_SIGN_SUPPORT == ENABLED || TLS_ECDHE_ECDSA_SUPPORT == ENABLED)
01513    error_t error;
01514    EcdsaSignature ecdsaSignature;
01515 
01516    //Initialize ECDSA signature
01517    ecdsaInitSignature(&ecdsaSignature);
01518 
01519    //Read the ASN.1 encoded ECDSA signature
01520    error = ecdsaReadSignature(signature, signatureLength, &ecdsaSignature);
01521    //Failed to decode ASN.1 structure?
01522    if(error)
01523       return error;
01524 
01525    //ECDSA signature verification
01526    error = ecdsaVerifySignature(params, key,
01527       digest, digestLength, &ecdsaSignature);
01528 
01529    //Free previously allocated resources
01530    ecdsaFreeSignature(&ecdsaSignature);
01531 
01532    //Return status code
01533    return error;
01534 #else
01535    //Not implemented
01536    return ERROR_NOT_IMPLEMENTED;
01537 #endif
01538 }
01539 
01540 
01541 /**
01542  * @brief Premaster secret generation (for PSK cipher suites)
01543  * @param[in] context Pointer to the TLS context
01544  * @return Error code
01545  **/
01546 
01547 error_t tlsGeneratePskPremasterSecret(TlsContext *context)
01548 {
01549    error_t error;
01550 
01551 #if (TLS_PSK_SUPPORT == ENABLED)
01552    //PSK key exchange method?
01553    if(context->keyExchMethod == TLS_KEY_EXCH_PSK)
01554    {
01555       size_t n;
01556 
01557       //Let N be the length of pre-shared key
01558       n = context->pskLen;
01559 
01560       //Check whether the output buffer is large enough to hold the premaster secret
01561       if((n * 2 + 4) <= TLS_MAX_PREMASTER_SECRET_SIZE)
01562       {
01563          //The premaster secret is formed as follows: if the PSK is N octets
01564          //long, concatenate a uint16 with the value N, N zero octets, a second
01565          //uint16 with the value N, and the PSK itself
01566          STORE16BE(n, context->premasterSecret);
01567          memset(context->premasterSecret + 2, 0, n);
01568          STORE16BE(n, context->premasterSecret + n + 2);
01569          memcpy(context->premasterSecret + n + 4, context->psk, n);
01570 
01571          //Save the length of the premaster secret
01572          context->premasterSecretLen = n * 2 + 4;
01573 
01574          //Premaster secret successfully generated
01575          error = NO_ERROR;
01576       }
01577       else
01578       {
01579          //Report an error
01580          error = ERROR_BUFFER_OVERFLOW;
01581       }
01582    }
01583    else
01584 #endif
01585 #if (TLS_RSA_PSK_SUPPORT == ENABLED || TLS_DHE_PSK_SUPPORT == ENABLED || \
01586    TLS_ECDHE_PSK_SUPPORT == ENABLED)
01587    //RSA_PSK, DHE_PSK or ECDHE_PSK key exchange method?
01588    if(context->keyExchMethod == TLS_KEY_EXCH_RSA_PSK ||
01589       context->keyExchMethod == TLS_KEY_EXCH_DHE_PSK ||
01590       context->keyExchMethod == TLS_KEY_EXCH_ECDHE_PSK)
01591    {
01592       size_t n;
01593 
01594       //Let N be the length of pre-shared key
01595       n = context->pskLen;
01596 
01597       //Check whether the output buffer is large enough to hold the premaster secret
01598       if((context->premasterSecretLen + n + 4) <= TLS_MAX_PREMASTER_SECRET_SIZE)
01599       {
01600          //The "other_secret" field comes from the Diffie-Hellman, ECDH or
01601          //RSA exchange (DHE_PSK, ECDH_PSK and RSA_PSK, respectively)
01602          memmove(context->premasterSecret + 2, context->premasterSecret,
01603             context->premasterSecretLen);
01604 
01605          //The "other_secret" field is preceded by a 2-byte length field
01606          STORE16BE(context->premasterSecretLen, context->premasterSecret);
01607 
01608          //if the PSK is N octets long, concatenate a uint16 with the value N
01609          STORE16BE(n, context->premasterSecret + context->premasterSecretLen + 2);
01610 
01611          //Concatenate the PSK itself
01612          memcpy(context->premasterSecret + context->premasterSecretLen + 4,
01613             context->psk, n);
01614 
01615          //Adjust the length of the premaster secret
01616          context->premasterSecretLen += n + 4;
01617 
01618          //Premaster secret successfully generated
01619          error = NO_ERROR;
01620       }
01621       else
01622       {
01623          //Report an error
01624          error = ERROR_BUFFER_OVERFLOW;
01625       }
01626    }
01627    else
01628 #endif
01629    //Invalid key exchange method?
01630    {
01631       //The specified key exchange method is not supported
01632       error = ERROR_UNSUPPORTED_KEY_EXCH_METHOD;
01633    }
01634 
01635    //Return status code
01636    return error;
01637 }
01638 
01639 
01640 /**
01641  * @brief Key generation
01642  * @param[in] context Pointer to the TLS context
01643  * @return Error code
01644  **/
01645 
01646 error_t tlsGenerateKeys(TlsContext *context)
01647 {
01648    error_t error;
01649    size_t i;
01650    size_t n;
01651    uint8_t temp;
01652 
01653    //Length of necessary key material
01654    n = 2 * (context->macKeyLen + context->encKeyLen + context->fixedIvLen);
01655 
01656    //Make sure that the key block is large enough
01657    if(n > sizeof(context->keyBlock))
01658       return ERROR_FAILURE;
01659 
01660    //Debug message
01661    TRACE_DEBUG("Generating keys...\r\n");
01662    TRACE_DEBUG("  Client random bytes:\r\n");
01663    TRACE_DEBUG_ARRAY("    ", &context->clientRandom, 32);
01664    TRACE_DEBUG("  Server random bytes:\r\n");
01665    TRACE_DEBUG_ARRAY("    ", &context->serverRandom, 32);
01666 
01667    //If a full handshake is being performed, the premaster secret
01668    //shall be first converted to the master secret
01669    if(!context->resume)
01670    {
01671       //Debug message
01672       TRACE_DEBUG("  Premaster secret:\r\n");
01673       TRACE_DEBUG_ARRAY("    ", context->premasterSecret, context->premasterSecretLen);
01674 
01675       //Convert the premaster secret to the master secret
01676       if(context->version == SSL_VERSION_3_0)
01677       {
01678          //SSL 3.0 does not use a PRF, instead makes use abundantly of MD5
01679          error = sslExpandKey(context->premasterSecret, context->premasterSecretLen,
01680             context->random, 64, context->masterSecret, 48);
01681       }
01682       else if(context->version <= TLS_VERSION_1_1)
01683       {
01684          //TLS 1.0 and 1.1 use a PRF that combines MD5 and SHA-1
01685          error = tlsPrf(context->premasterSecret, context->premasterSecretLen,
01686             "master secret", context->random, 64, context->masterSecret, 48);
01687       }
01688       else
01689       {
01690          //TLS 1.2 PRF uses SHA-256 or a stronger hash algorithm
01691          //as the core function in its construction
01692          error = tlsPrf2(context->prfHashAlgo, context->premasterSecret,
01693             context->premasterSecretLen, "master secret",
01694             context->random, 64, context->masterSecret, 48);
01695       }
01696 
01697       //Check the return status
01698       if(error)
01699          return error;
01700 
01701       //The premaster secret should be deleted from memory
01702       //once the master secret has been computed
01703       memset(context->premasterSecret, 0, 48);
01704    }
01705 
01706    //Debug message
01707    TRACE_DEBUG("  Master secret:\r\n");
01708    TRACE_DEBUG_ARRAY("    ", context->masterSecret, 48);
01709 
01710    //Exchange client and server random bytes
01711    for(i = 0; i < 32; i++)
01712    {
01713       //Swap each byte
01714       temp = context->random[i];
01715       context->random[i] = context->random[i + 32];
01716       context->random[i + 32] = temp;
01717    }
01718 
01719    //Perform key expansion
01720    if(context->version == SSL_VERSION_3_0)
01721    {
01722       //SSL 3.0 does not use a PRF, instead makes use abundantly of MD5
01723       error = sslExpandKey(context->masterSecret, 48,
01724          context->random, 64, context->keyBlock, n);
01725    }
01726    else if(context->version <= TLS_VERSION_1_1)
01727    {
01728       //TLS 1.0 and 1.1 use a PRF that combines MD5 and SHA-1
01729       error = tlsPrf(context->masterSecret, 48, "key expansion",
01730          context->random, 64, context->keyBlock, n);
01731    }
01732    else
01733    {
01734       //TLS 1.2 PRF uses SHA-256 or a stronger hash algorithm
01735       //as the core function in its construction
01736       error = tlsPrf2(context->prfHashAlgo, context->masterSecret, 48,
01737          "key expansion", context->random, 64, context->keyBlock, n);
01738    }
01739 
01740    //Exchange client and server random bytes
01741    for(i = 0; i < 32; i++)
01742    {
01743       //Swap each byte
01744       temp = context->random[i];
01745       context->random[i] = context->random[i + 32];
01746       context->random[i + 32] = temp;
01747    }
01748 
01749    //Any error while performing key expansion?
01750    if(error)
01751       return error;
01752 
01753    //Debug message
01754    TRACE_DEBUG("  Key block:\r\n");
01755    TRACE_DEBUG_ARRAY("    ", context->keyBlock, n);
01756 
01757    //TLS operates as a client?
01758    if(context->entity == TLS_CONNECTION_END_CLIENT)
01759    {
01760       //MAC keys
01761       context->writeMacKey = context->keyBlock;
01762       context->readMacKey = context->writeMacKey + context->macKeyLen;
01763       //Encryption keys
01764       context->writeEncKey = context->readMacKey + context->macKeyLen;
01765       context->readEncKey = context->writeEncKey + context->encKeyLen;
01766       //Initialization vectors
01767       context->writeIv = context->readEncKey + context->encKeyLen;
01768       context->readIv = context->writeIv + context->fixedIvLen;
01769    }
01770    //TLS operates as a server?
01771    else
01772    {
01773       //MAC keys
01774       context->readMacKey = context->keyBlock;
01775       context->writeMacKey = context->readMacKey + context->macKeyLen;
01776       //Encryption keys
01777       context->readEncKey = context->writeMacKey + context->macKeyLen;
01778       context->writeEncKey = context->readEncKey + context->encKeyLen;
01779       //Initialization vectors
01780       context->readIv = context->writeEncKey + context->encKeyLen;
01781       context->writeIv = context->readIv + context->fixedIvLen;
01782    }
01783 
01784    //Dump MAC keys for debugging purpose
01785    if(context->macKeyLen > 0)
01786    {
01787       TRACE_DEBUG("  Write MAC key:\r\n");
01788       TRACE_DEBUG_ARRAY("    ", context->writeMacKey, context->macKeyLen);
01789       TRACE_DEBUG("  Read MAC key:\r\n");
01790       TRACE_DEBUG_ARRAY("    ", context->readMacKey, context->macKeyLen);
01791    }
01792 
01793    //Dump encryption keys for debugging purpose
01794    TRACE_DEBUG("  Write encryption key:\r\n");
01795    TRACE_DEBUG_ARRAY("    ", context->writeEncKey, context->encKeyLen);
01796    TRACE_DEBUG("  Read encryption key:\r\n");
01797    TRACE_DEBUG_ARRAY("    ", context->readEncKey, context->encKeyLen);
01798 
01799    //Dump initialization vectors for debugging purpose
01800    if(context->fixedIvLen > 0)
01801    {
01802       TRACE_DEBUG("  Write IV:\r\n");
01803       TRACE_DEBUG_ARRAY("    ", context->writeIv, context->fixedIvLen);
01804       TRACE_DEBUG("  Read IV:\r\n");
01805       TRACE_DEBUG_ARRAY("    ", context->readIv, context->fixedIvLen);
01806    }
01807 
01808    //Key generation is successful
01809    return NO_ERROR;
01810 }
01811 
01812 
01813 /**
01814  * @brief Pseudorandom function (TLS 1.0 and 1.1)
01815  *
01816  * The pseudorandom function (PRF) takes as input a secret, a seed, and
01817  * an identifying label and produces an output of arbitrary length. This
01818  * function is used to expand secrets into blocks of data for the purpose
01819  * of key generation
01820  *
01821  * @param[in] secret Pointer to the secret
01822  * @param[in] secretLength Length of the secret
01823  * @param[in] label Identifying label (NULL-terminated string)
01824  * @param[in] seed Pointer to the seed
01825  * @param[in] seedLength Length of the seed
01826  * @param[out] output Pointer to the output
01827  * @param[in] outputLength Desired output length
01828  * @return Error code
01829  **/
01830 
01831 error_t tlsPrf(const uint8_t *secret, size_t secretLength, const char_t *label,
01832    const uint8_t *seed, size_t seedLength, uint8_t *output, size_t outputLength)
01833 {
01834    uint_t i;
01835    uint_t j;
01836    size_t labelLength;
01837    size_t sLength;
01838    const uint8_t *s1;
01839    const uint8_t *s2;
01840    HmacContext *hmacContext;
01841    uint8_t a[SHA1_DIGEST_SIZE];
01842 
01843    //Allocate a memory buffer to hold the HMAC context
01844    hmacContext = tlsAllocMem(sizeof(HmacContext));
01845    //Failed to allocate memory?
01846    if(hmacContext == NULL)
01847       return ERROR_OUT_OF_MEMORY;
01848 
01849    //Compute the length of the label
01850    labelLength = strlen(label);
01851 
01852    //The secret is partitioned into two halves S1 and S2
01853    //with the possibility of one shared byte
01854    sLength = (secretLength + 1) / 2;
01855    //S1 is taken from the first half of the secret
01856    s1 = secret;
01857    //S2 is taken from the second half
01858    s2 = secret + secretLength - sLength;
01859 
01860    //First compute A(1) = HMAC_MD5(S1, label + seed)
01861    hmacInit(hmacContext, MD5_HASH_ALGO, s1, sLength);
01862    hmacUpdate(hmacContext, label, labelLength);
01863    hmacUpdate(hmacContext, seed, seedLength);
01864    hmacFinal(hmacContext, a);
01865 
01866    //Apply the data expansion function P_MD5
01867    for(i = 0; i < outputLength; )
01868    {
01869       //Compute HMAC_MD5(S1, A(i) + label + seed)
01870       hmacInit(hmacContext, MD5_HASH_ALGO, s1, sLength);
01871       hmacUpdate(hmacContext, a, MD5_DIGEST_SIZE);
01872       hmacUpdate(hmacContext, label, labelLength);
01873       hmacUpdate(hmacContext, seed, seedLength);
01874       hmacFinal(hmacContext, NULL);
01875 
01876       //Copy the resulting digest
01877       for(j = 0; i < outputLength && j < MD5_DIGEST_SIZE; i++, j++)
01878          output[i] = hmacContext->digest[j];
01879 
01880       //Compute A(i + 1) = HMAC_MD5(S1, A(i))
01881       hmacInit(hmacContext, MD5_HASH_ALGO, s1, sLength);
01882       hmacUpdate(hmacContext, a, MD5_DIGEST_SIZE);
01883       hmacFinal(hmacContext, a);
01884    }
01885 
01886    //First compute A(1) = HMAC_SHA1(S2, label + seed)
01887    hmacInit(hmacContext, SHA1_HASH_ALGO, s2, sLength);
01888    hmacUpdate(hmacContext, label, labelLength);
01889    hmacUpdate(hmacContext, seed, seedLength);
01890    hmacFinal(hmacContext, a);
01891 
01892    //Apply the data expansion function P_SHA1
01893    for(i = 0; i < outputLength; )
01894    {
01895       //Compute HMAC_SHA1(S2, A(i) + label + seed)
01896       hmacInit(hmacContext, SHA1_HASH_ALGO, s2, sLength);
01897       hmacUpdate(hmacContext, a, SHA1_DIGEST_SIZE);
01898       hmacUpdate(hmacContext, label, labelLength);
01899       hmacUpdate(hmacContext, seed, seedLength);
01900       hmacFinal(hmacContext, NULL);
01901 
01902       //Copy the resulting digest
01903       for(j = 0; i < outputLength && j < SHA1_DIGEST_SIZE; i++, j++)
01904          output[i] ^= hmacContext->digest[j];
01905 
01906       //Compute A(i + 1) = HMAC_SHA1(S2, A(i))
01907       hmacInit(hmacContext, SHA1_HASH_ALGO, s2, sLength);
01908       hmacUpdate(hmacContext, a, SHA1_DIGEST_SIZE);
01909       hmacFinal(hmacContext, a);
01910    }
01911 
01912    //Free previously allocated memory
01913    tlsFreeMem(hmacContext);
01914    //Successful processing
01915    return NO_ERROR;
01916 }
01917 
01918 
01919 /**
01920  * @brief Pseudorandom function (TLS 1.2)
01921  *
01922  * The pseudorandom function (PRF) takes as input a secret, a seed, and
01923  * an identifying label and produces an output of arbitrary length. This
01924  * function is used to expand secrets into blocks of data for the purpose
01925  * of key generation
01926  *
01927  * @param[in] hash Hash function used to compute PRF
01928  * @param[in] secret Pointer to the secret
01929  * @param[in] secretLength Length of the secret
01930  * @param[in] label Identifying label (NULL-terminated string)
01931  * @param[in] seed Pointer to the seed
01932  * @param[in] seedLength Length of the seed
01933  * @param[out] output Pointer to the output
01934  * @param[in] outputLength Desired output length
01935  * @return Error code
01936  **/
01937 
01938 error_t tlsPrf2(const HashAlgo *hash, const uint8_t *secret, size_t secretLength,
01939    const char_t *label, const uint8_t *seed, size_t seedLength, uint8_t *output, size_t outputLength)
01940 {
01941    size_t n;
01942    size_t labelLength;
01943    HmacContext *hmacContext;
01944    uint8_t a[MAX_HASH_DIGEST_SIZE];
01945 
01946    //Allocate a memory buffer to hold the HMAC context
01947    hmacContext = tlsAllocMem(sizeof(HmacContext));
01948    //Failed to allocate memory?
01949    if(hmacContext == NULL)
01950       return ERROR_OUT_OF_MEMORY;
01951 
01952    //Compute the length of the label
01953    labelLength = strlen(label);
01954 
01955    //First compute A(1) = HMAC_hash(secret, label + seed)
01956    hmacInit(hmacContext, hash, secret, secretLength);
01957    hmacUpdate(hmacContext, label, labelLength);
01958    hmacUpdate(hmacContext, seed, seedLength);
01959    hmacFinal(hmacContext, a);
01960 
01961    //Apply the data expansion function P_hash
01962    while(outputLength > 0)
01963    {
01964       //Compute HMAC_hash(secret, A(i) + label + seed)
01965       hmacInit(hmacContext, hash, secret, secretLength);
01966       hmacUpdate(hmacContext, a, hash->digestSize);
01967       hmacUpdate(hmacContext, label, labelLength);
01968       hmacUpdate(hmacContext, seed, seedLength);
01969       hmacFinal(hmacContext, NULL);
01970 
01971       //Calculate the number of bytes to copy
01972       n = MIN(outputLength, hash->digestSize);
01973       //Copy the resulting digest
01974       memcpy(output, hmacContext->digest, n);
01975 
01976       //Compute A(i + 1) = HMAC_hash(secret, A(i))
01977       hmacInit(hmacContext, hash, secret, secretLength);
01978       hmacUpdate(hmacContext, a, hash->digestSize);
01979       hmacFinal(hmacContext, a);
01980 
01981       //Advance data pointer
01982       output += n;
01983       //Decrement byte counter
01984       outputLength -= n;
01985    }
01986 
01987    //Free previously allocated memory
01988    tlsFreeMem(hmacContext);
01989    //Successful processing
01990    return NO_ERROR;
01991 }
01992 
01993 
01994 /**
01995  * @brief Check whether a certificate is acceptable
01996  * @param[in] cert End entity certificate
01997  * @param[in] certTypes List of supported certificate types
01998  * @param[in] numCertTypes Size of the list that contains the supported certificate types
01999  * @param[in] signHashAlgos List of supported signature algorithms
02000  * @param[in] curveList List of supported elliptic curves
02001  * @param[in] certAuthorities List of trusted CA
02002  * @return TRUE if the specified certificate conforms to the requirements, else FALSE
02003  **/
02004 
02005 bool_t tlsIsCertificateAcceptable(const TlsCertDesc *cert,
02006    const uint8_t *certTypes, size_t numCertTypes, const TlsSignHashAlgos *signHashAlgos,
02007    const TlsEllipticCurveList *curveList, const TlsCertAuthorities *certAuthorities)
02008 {
02009    size_t i;
02010    size_t n;
02011    size_t length;
02012    bool_t acceptable;
02013 
02014    //Make sure that a valid certificate has been loaded
02015    if(!cert->certChain || !cert->certChainLength)
02016       return FALSE;
02017 
02018    //This flag tells whether the certificate is acceptable
02019    acceptable = TRUE;
02020 
02021    //Filter out certificates with unsupported type
02022    if(numCertTypes > 0)
02023    {
02024       //Loop through the list of supported certificate types
02025       for(acceptable = FALSE, i = 0; i < numCertTypes; i++)
02026       {
02027          //Check whether the certificate type is acceptable
02028          if(certTypes[i] == cert->type)
02029          {
02030             acceptable = TRUE;
02031             break;
02032          }
02033       }
02034    }
02035 
02036    //Filter out certificates that are signed with an unsupported
02037    //hash/signature algorithm
02038    if(acceptable && signHashAlgos != NULL)
02039    {
02040       //Retrieve the number of items in the list
02041       n = ntohs(signHashAlgos->length) / sizeof(TlsSignHashAlgo);
02042 
02043       //Loop through the list of supported hash/signature algorithm pairs
02044       for(acceptable = FALSE, i = 0; i < n; i++)
02045       {
02046          //The certificate must be signed using a valid hash/signature algorithm pair
02047          if(signHashAlgos->value[i].signature == cert->signAlgo &&
02048             signHashAlgos->value[i].hash == cert->hashAlgo)
02049          {
02050             acceptable = TRUE;
02051             break;
02052          }
02053       }
02054    }
02055 
02056    //Check whether the certificate contains an ECDSA public key
02057    if(cert->type == TLS_CERT_ECDSA_SIGN)
02058    {
02059       //Filter out ECDSA certificates that use an unsupported elliptic curve
02060       if(acceptable && curveList != NULL)
02061       {
02062          //Retrieve the number of items in the list
02063          n = ntohs(curveList->length) / sizeof(uint16_t);
02064 
02065          //Loop through the list of supported elliptic curves
02066          for(acceptable = FALSE, i = 0; i < n; i++)
02067          {
02068             //Check whether the elliptic curve is supported
02069             if(ntohs(curveList->value[i]) == cert->namedCurve)
02070             {
02071                acceptable = TRUE;
02072                break;
02073             }
02074          }
02075       }
02076    }
02077 
02078    //Filter out certificates that are issued by a non trusted CA
02079    if(acceptable && certAuthorities != NULL)
02080    {
02081       //Retrieve the length of the list
02082       length = ntohs(certAuthorities->length);
02083 
02084       //If the certificate authorities list is empty, then the client
02085       //may send any certificate of the appropriate type
02086       if(length > 0)
02087       {
02088          error_t error;
02089          const uint8_t *p;
02090          const char_t *pemCert;
02091          size_t pemCertLength;
02092          uint8_t *derCert;
02093          size_t derCertSize;
02094          size_t derCertLength;
02095          X509CertificateInfo *certInfo;
02096 
02097          //The list of acceptable certificate authorities describes the known roots CA
02098          acceptable = FALSE;
02099 
02100          //Point to the first distinguished name
02101          p = certAuthorities->value;
02102 
02103          //Point to the end entity certificate
02104          pemCert = cert->certChain;
02105          //Get the total length, in bytes, of the certificate chain
02106          pemCertLength = cert->certChainLength;
02107 
02108          //DER encoded certificate
02109          derCert = NULL;
02110          derCertSize = 0;
02111          derCertLength = 0;
02112 
02113          //Start of exception handling block
02114          do
02115          {
02116             //Allocate a memory buffer to store X.509 certificate info
02117             certInfo = tlsAllocMem(sizeof(X509CertificateInfo));
02118             //Failed to allocate memory?
02119             if(certInfo == NULL)
02120                break;
02121 
02122             //Point to the last certificate of the chain
02123             do
02124             {
02125                //Read PEM certificates, one by one
02126                error = pemReadCertificate(&pemCert, &pemCertLength,
02127                   &derCert, &derCertSize, &derCertLength);
02128 
02129                //Loop as long as necessary
02130             } while(!error);
02131 
02132             //Any error to report?
02133             if(error != ERROR_END_OF_FILE)
02134                break;
02135 
02136             //Parse the last certificate of the chain
02137             error = x509ParseCertificate(derCert, derCertLength, certInfo);
02138             //Failed to parse the X.509 certificate?
02139             if(error)
02140                break;
02141 
02142             //Parse each distinguished name of the list
02143             while(length > 0)
02144             {
02145                //Sanity check
02146                if(length < 2)
02147                   break;
02148 
02149                //Each distinguished name is preceded by a 2-byte length field
02150                n = LOAD16BE(p);
02151 
02152                //Make sure the length field is valid
02153                if(length < (n + 2))
02154                   break;
02155 
02156                //Check if the distinguished name matches the root CA
02157                if(n == certInfo->issuer.rawDataLen && !memcmp(p + 2, certInfo->issuer.rawData, n))
02158                {
02159                   acceptable = TRUE;
02160                   break;
02161                }
02162 
02163                //Advance data pointer
02164                p += n + 2;
02165                //Number of bytes left in the list
02166                length -= n + 2;
02167             }
02168 
02169             //End of exception handling block
02170          } while(0);
02171 
02172          //Release previously allocated memory
02173          tlsFreeMem(derCert);
02174          tlsFreeMem(certInfo);
02175       }
02176    }
02177 
02178    //The return value specifies whether all the criteria were matched
02179    return acceptable;
02180 }
02181 
02182 
02183 /**
02184  * @brief Retrieve the certificate type
02185  * @param[in] certInfo X.509 certificate
02186  * @param[out] certType Certificate type
02187  * @param[out] certSignAlgo Signature algorithm that has been used to sign the certificate
02188  * @param[out] certHashAlgo Hash algorithm that has been used to sign the certificate
02189  * @param[out] namedCurve Elliptic curve (only for ECDSA certificates)
02190  * @return Error code
02191  **/
02192 
02193 error_t tlsGetCertificateType(const X509CertificateInfo *certInfo, TlsCertificateType *certType,
02194    TlsSignatureAlgo *certSignAlgo, TlsHashAlgo *certHashAlgo, TlsEcNamedCurve *namedCurve)
02195 {
02196    //Check parameters
02197    if(certInfo == NULL || certType == NULL || certSignAlgo == NULL ||
02198       certHashAlgo == NULL || namedCurve == NULL)
02199    {
02200       //Report an error
02201       return ERROR_INVALID_PARAMETER;
02202    }
02203 
02204 #if (TLS_RSA_SIGN_SUPPORT == ENABLED || TLS_RSA_SUPPORT == ENABLED || \
02205    TLS_DHE_RSA_SUPPORT == ENABLED || TLS_ECDHE_RSA_SUPPORT == ENABLED)
02206    //A valid RSA public key has been found?
02207    if(!oidComp(certInfo->subjectPublicKeyInfo.oid, certInfo->subjectPublicKeyInfo.oidLen,
02208       RSA_ENCRYPTION_OID, sizeof(RSA_ENCRYPTION_OID)))
02209    {
02210       //Save certificate type
02211       *certType = TLS_CERT_RSA_SIGN;
02212       //Elliptic curve cryptography is not used
02213       *namedCurve = TLS_EC_CURVE_NONE;
02214    }
02215    else
02216 #endif
02217 #if (TLS_DSA_SIGN_SUPPORT == ENABLED || TLS_DHE_DSS_SUPPORT == ENABLED)
02218    //A valid DSA public key has been found?
02219    if(!oidComp(certInfo->subjectPublicKeyInfo.oid, certInfo->subjectPublicKeyInfo.oidLen,
02220       DSA_OID, sizeof(DSA_OID)))
02221    {
02222       //Save certificate type
02223       *certType = TLS_CERT_DSS_SIGN;
02224       //Elliptic curve cryptography is not used
02225       *namedCurve = TLS_EC_CURVE_NONE;
02226    }
02227    else
02228 #endif
02229 #if (TLS_ECDSA_SIGN_SUPPORT == ENABLED || TLS_ECDHE_ECDSA_SUPPORT == ENABLED)
02230    //A valid EC public key has been found?
02231    if(!oidComp(certInfo->subjectPublicKeyInfo.oid, certInfo->subjectPublicKeyInfo.oidLen,
02232       EC_PUBLIC_KEY_OID, sizeof(EC_PUBLIC_KEY_OID)))
02233    {
02234       //Save certificate type
02235       *certType = TLS_CERT_ECDSA_SIGN;
02236 
02237       //Retrieve the named curve that has been used to generate the EC public key
02238       *namedCurve = tlsGetNamedCurve(certInfo->subjectPublicKeyInfo.ecParams.namedCurve,
02239          certInfo->subjectPublicKeyInfo.ecParams.namedCurveLen);
02240    }
02241    else
02242 #endif
02243    //The certificate does not contain any valid public key...
02244    {
02245       //Report an error
02246       return ERROR_BAD_CERTIFICATE;
02247    }
02248 
02249    //Retrieve the signature algorithm that has been used to sign the certificate
02250    if(certInfo->signatureAlgo == NULL)
02251    {
02252       //Invalid certificate
02253       return ERROR_BAD_CERTIFICATE;
02254    }
02255 #if (TLS_RSA_SIGN_SUPPORT == ENABLED)
02256    else if(!oidComp(certInfo->signatureAlgo, certInfo->signatureAlgoLen,
02257       MD5_WITH_RSA_ENCRYPTION_OID, sizeof(MD5_WITH_RSA_ENCRYPTION_OID)))
02258    {
02259       //MD5 with RSA signature algorithm
02260       *certSignAlgo = TLS_SIGN_ALGO_RSA;
02261       *certHashAlgo = TLS_HASH_ALGO_MD5;
02262    }
02263    else if(!oidComp(certInfo->signatureAlgo, certInfo->signatureAlgoLen,
02264       SHA1_WITH_RSA_ENCRYPTION_OID, sizeof(SHA1_WITH_RSA_ENCRYPTION_OID)))
02265    {
02266       //SHA-1 with RSA signature algorithm
02267       *certSignAlgo = TLS_SIGN_ALGO_RSA;
02268       *certHashAlgo = TLS_HASH_ALGO_SHA1;
02269    }
02270    else if(!oidComp(certInfo->signatureAlgo, certInfo->signatureAlgoLen,
02271       SHA256_WITH_RSA_ENCRYPTION_OID, sizeof(SHA256_WITH_RSA_ENCRYPTION_OID)))
02272    {
02273       //SHA-256 with RSA signature algorithm
02274       *certSignAlgo = TLS_SIGN_ALGO_RSA;
02275       *certHashAlgo = TLS_HASH_ALGO_SHA256;
02276    }
02277    else if(!oidComp(certInfo->signatureAlgo, certInfo->signatureAlgoLen,
02278       SHA384_WITH_RSA_ENCRYPTION_OID, sizeof(SHA384_WITH_RSA_ENCRYPTION_OID)))
02279    {
02280       //SHA-384 with RSA signature algorithm
02281       *certSignAlgo = TLS_SIGN_ALGO_RSA;
02282       *certHashAlgo = TLS_HASH_ALGO_SHA384;
02283    }
02284    else if(!oidComp(certInfo->signatureAlgo, certInfo->signatureAlgoLen,
02285       SHA512_WITH_RSA_ENCRYPTION_OID, sizeof(SHA512_WITH_RSA_ENCRYPTION_OID)))
02286    {
02287       //SHA-512 with RSA signature algorithm
02288       *certSignAlgo = TLS_SIGN_ALGO_RSA;
02289       *certHashAlgo = TLS_HASH_ALGO_SHA512;
02290    }
02291 #endif
02292 #if (TLS_DSA_SIGN_SUPPORT == ENABLED)
02293    else if(!oidComp(certInfo->signatureAlgo, certInfo->signatureAlgoLen,
02294       DSA_WITH_SHA1_OID, sizeof(DSA_WITH_SHA1_OID)))
02295    {
02296       //DSA with SHA-1 signature algorithm
02297       *certSignAlgo = TLS_SIGN_ALGO_DSA;
02298       *certHashAlgo = TLS_HASH_ALGO_SHA1;
02299    }
02300    else if(!oidComp(certInfo->signatureAlgo, certInfo->signatureAlgoLen,
02301       DSA_WITH_SHA224_OID, sizeof(DSA_WITH_SHA224_OID)))
02302    {
02303       //DSA with SHA-224 signature algorithm
02304       *certSignAlgo = TLS_SIGN_ALGO_DSA;
02305       *certHashAlgo = TLS_HASH_ALGO_SHA224;
02306    }
02307    else if(!oidComp(certInfo->signatureAlgo, certInfo->signatureAlgoLen,
02308       DSA_WITH_SHA256_OID, sizeof(DSA_WITH_SHA256_OID)))
02309    {
02310       //DSA with SHA-256 signature algorithm
02311       *certSignAlgo = TLS_SIGN_ALGO_DSA;
02312       *certHashAlgo = TLS_HASH_ALGO_SHA256;
02313    }
02314 #endif
02315 #if (TLS_ECDSA_SIGN_SUPPORT == ENABLED)
02316    else if(!oidComp(certInfo->signatureAlgo, certInfo->signatureAlgoLen,
02317       ECDSA_WITH_SHA1_OID, sizeof(ECDSA_WITH_SHA1_OID)))
02318    {
02319       //ECDSA with SHA-1 signature algorithm
02320       *certSignAlgo = TLS_SIGN_ALGO_ECDSA;
02321       *certHashAlgo = TLS_HASH_ALGO_SHA1;
02322    }
02323    else if(!oidComp(certInfo->signatureAlgo, certInfo->signatureAlgoLen,
02324       ECDSA_WITH_SHA224_OID, sizeof(ECDSA_WITH_SHA224_OID)))
02325    {
02326       //ECDSA with SHA-224 signature algorithm
02327       *certSignAlgo = TLS_SIGN_ALGO_ECDSA;
02328       *certHashAlgo = TLS_HASH_ALGO_SHA224;
02329    }
02330    else if(!oidComp(certInfo->signatureAlgo, certInfo->signatureAlgoLen,
02331       ECDSA_WITH_SHA256_OID, sizeof(ECDSA_WITH_SHA256_OID)))
02332    {
02333       //ECDSA with SHA-256 signature algorithm
02334       *certSignAlgo = TLS_SIGN_ALGO_ECDSA;
02335       *certHashAlgo = TLS_HASH_ALGO_SHA256;
02336    }
02337    else if(!oidComp(certInfo->signatureAlgo, certInfo->signatureAlgoLen,
02338       ECDSA_WITH_SHA384_OID, sizeof(ECDSA_WITH_SHA384_OID)))
02339    {
02340       //ECDSA with SHA-384 signature algorithm
02341       *certSignAlgo = TLS_SIGN_ALGO_ECDSA;
02342       *certHashAlgo = TLS_HASH_ALGO_SHA384;
02343    }
02344    else if(!oidComp(certInfo->signatureAlgo, certInfo->signatureAlgoLen,
02345       ECDSA_WITH_SHA512_OID, sizeof(ECDSA_WITH_SHA512_OID)))
02346    {
02347       //ECDSA with SHA-512 signature algorithm
02348       *certSignAlgo = TLS_SIGN_ALGO_ECDSA;
02349       *certHashAlgo = TLS_HASH_ALGO_SHA512;
02350    }
02351 #endif
02352    else
02353    {
02354       //The signature algorithm is not supported...
02355       return ERROR_BAD_CERTIFICATE;
02356    }
02357 
02358    //X.509 certificate successfully parsed
02359    return NO_ERROR;
02360 }
02361 
02362 
02363 /**
02364  * @brief Find the specified extension
02365  * @param[in] data Pointer to the list of extensions
02366  * @param[in] length Length in bytes of the list
02367  * @param[in] type Expected extension type
02368  * @return If the specified extension was found, a pointer to the corresponding
02369  *   extension is returned. Otherwise NULL pointer is returned
02370  **/
02371 
02372 const TlsExtension *tlsGetExtension(const uint8_t *data, size_t length, uint16_t type)
02373 {
02374    size_t n;
02375    const TlsExtension *extension;
02376 
02377    //Sanity check
02378    if(length < 2)
02379       return NULL;
02380 
02381    //Retrieve the length of the list
02382    n = LOAD16BE(data);
02383 
02384    //Sanity check
02385    if(length < (n + 2))
02386       return NULL;
02387 
02388    //Point to the first extension of the list
02389    data += 2;
02390 
02391    //Parse the list of extensions offered by the peer
02392    while(n > 0)
02393    {
02394       //Point to the current extension
02395       extension = (TlsExtension *) data;
02396 
02397       //Check the length of the extension
02398       if(n < sizeof(TlsExtension))
02399          break;
02400       if(n < (sizeof(TlsExtension) + ntohs(extension->length)))
02401          break;
02402 
02403       //Check whether the extension type matches the specified one
02404       if(ntohs(extension->type) == type)
02405          return extension;
02406 
02407       //Jump to the next extension
02408       data += sizeof(TlsExtension) + ntohs(extension->length);
02409       //Remaining bytes to process
02410       n -= sizeof(TlsExtension) + ntohs(extension->length);
02411    }
02412 
02413    //The specified extension type was not found
02414    return NULL;
02415 }
02416 
02417 
02418 /**
02419  * @brief Convert TLS version to string representation
02420  * @param[in] version Version number
02421  * @return Cipher suite name
02422  **/
02423 
02424 const char_t *tlsGetVersionName(uint16_t version)
02425 {
02426    //TLS versions
02427    static const char_t *label[] = {"SSL 3.0", "TLS 1.0", "TLS 1.1", "TLS 1.2", "Unknown"};
02428 
02429    //Check current version
02430    if(version == SSL_VERSION_3_0)
02431       return label[0];
02432    else if(version == TLS_VERSION_1_0)
02433       return label[1];
02434    else if(version == TLS_VERSION_1_1)
02435       return label[2];
02436    else if(version == TLS_VERSION_1_2)
02437       return label[3];
02438    else
02439       return label[4];
02440 }
02441 
02442 
02443 /**
02444  * @brief Get the hash algorithm that matches the specified identifier
02445  * @param[in] hashAlgoId Hash algorithm identifier
02446  * @return Cipher suite name
02447  **/
02448 
02449 const HashAlgo *tlsGetHashAlgo(uint8_t hashAlgoId)
02450 {
02451    //MD5 hash identifier?
02452    if(hashAlgoId == TLS_HASH_ALGO_MD5)
02453       return MD5_HASH_ALGO;
02454    //SHA-1 hash identifier?
02455    else if(hashAlgoId == TLS_HASH_ALGO_SHA1)
02456       return SHA1_HASH_ALGO;
02457    //SHA-256 hash identifier?
02458    else if(hashAlgoId == TLS_HASH_ALGO_SHA256)
02459       return SHA256_HASH_ALGO;
02460 #if (TLS_SHA224_SUPPORT == ENABLED)
02461    //SHA-224 hash identifier?
02462    else if(hashAlgoId == TLS_HASH_ALGO_SHA224)
02463       return SHA224_HASH_ALGO;
02464 #endif
02465 #if (TLS_SHA384_SUPPORT == ENABLED)
02466    //SHA-384 hash identifier?
02467    else if(hashAlgoId == TLS_HASH_ALGO_SHA384)
02468       return SHA384_HASH_ALGO;
02469 #endif
02470 #if (TLS_SHA512_SUPPORT == ENABLED)
02471    //SHA-512 hash identifier?
02472    else if(hashAlgoId == TLS_HASH_ALGO_SHA512)
02473       return SHA512_HASH_ALGO;
02474 #endif
02475    //Unknown hash identifier?
02476    else
02477       return NULL;
02478 }
02479 
02480 
02481 /**
02482  * @brief Get the EC domain parameters that match the specified named curve
02483  * @param[in] namedCurve Elliptic curve identifier
02484  * @return Elliptic curve domain parameters
02485  **/
02486 
02487 const EcCurveInfo *tlsGetCurveInfo(uint16_t namedCurve)
02488 {
02489 #if (TLS_ECDH_ANON_SUPPORT == ENABLED || TLS_ECDHE_RSA_SUPPORT == ENABLED || \
02490    TLS_ECDHE_ECDSA_SUPPORT == ENABLED || TLS_ECDHE_PSK_SUPPORT == ENABLED)
02491    //Explicit prime elliptic curves are not supported
02492    if(namedCurve == TLS_EC_CURVE_ARBITRARY_EXPLICIT_PRIME)
02493       return NULL;
02494    //Explicit characteristic-2 elliptic curves are not supported
02495    else if(namedCurve == TLS_EC_CURVE_ARBITRARY_EXPLICIT_CHAR2)
02496       return NULL;
02497 #if (TLS_SECP160K1_SUPPORT == ENABLED)
02498    //secp160k1 elliptic curve?
02499    else if(namedCurve == TLS_EC_CURVE_SECP160K1)
02500       return SECP160K1_CURVE;
02501 #endif
02502 #if (TLS_SECP160R1_SUPPORT == ENABLED)
02503    //secp160r1 elliptic curve?
02504    else if(namedCurve == TLS_EC_CURVE_SECP160R1)
02505       return SECP160R1_CURVE;
02506 #endif
02507 #if (TLS_SECP160R2_SUPPORT == ENABLED)
02508    //secp160r2 elliptic curve?
02509    else if(namedCurve == TLS_EC_CURVE_SECP160R2)
02510       return SECP160R2_CURVE;
02511 #endif
02512 #if (TLS_SECP192K1_SUPPORT == ENABLED)
02513    //secp192k1 elliptic curve?
02514    else if(namedCurve == TLS_EC_CURVE_SECP192K1)
02515       return SECP192K1_CURVE;
02516 #endif
02517 #if (TLS_SECP192R1_SUPPORT == ENABLED)
02518    //secp192r1 elliptic curve?
02519    else if(namedCurve == TLS_EC_CURVE_SECP192R1)
02520       return SECP192R1_CURVE;
02521 #endif
02522 #if (TLS_SECP224K1_SUPPORT == ENABLED)
02523    //secp224k1 elliptic curve?
02524    else if(namedCurve == TLS_EC_CURVE_SECP224K1)
02525       return SECP224K1_CURVE;
02526 #endif
02527 #if (TLS_SECP224R1_SUPPORT == ENABLED)
02528    //secp224r1 elliptic curve?
02529    else if(namedCurve == TLS_EC_CURVE_SECP224R1)
02530       return SECP224R1_CURVE;
02531 #endif
02532 #if (TLS_SECP256K1_SUPPORT == ENABLED)
02533    //secp256k1 elliptic curve?
02534    else if(namedCurve == TLS_EC_CURVE_SECP256K1)
02535       return SECP256K1_CURVE;
02536 #endif
02537 #if (TLS_SECP256R1_SUPPORT == ENABLED)
02538    //secp256r1 elliptic curve?
02539    else if(namedCurve == TLS_EC_CURVE_SECP256R1)
02540       return SECP256R1_CURVE;
02541 #endif
02542 #if (TLS_SECP384R1_SUPPORT == ENABLED)
02543    //secp384r1 elliptic curve?
02544    else if(namedCurve == TLS_EC_CURVE_SECP384R1)
02545       return SECP384R1_CURVE;
02546 #endif
02547 #if (TLS_SECP521R1_SUPPORT == ENABLED)
02548    //secp521r1 elliptic curve?
02549    else if(namedCurve == TLS_EC_CURVE_SECP521R1)
02550       return SECP521R1_CURVE;
02551 #endif
02552 #if (TLS_BRAINPOOLP256R1_SUPPORT == ENABLED)
02553    //brainpoolP256r1 elliptic curve?
02554    else if(namedCurve == TLS_EC_CURVE_BRAINPOOLP256R1)
02555       return BRAINPOOLP256R1_CURVE;
02556 #endif
02557 #if (TLS_BRAINPOOLP384R1_SUPPORT == ENABLED)
02558    //brainpoolP384r1 elliptic curve?
02559    else if(namedCurve == TLS_EC_CURVE_BRAINPOOLP384R1)
02560       return BRAINPOOLP384R1_CURVE;
02561 #endif
02562 #if (TLS_BRAINPOOLP512R1_SUPPORT == ENABLED)
02563    //brainpoolP512r1 elliptic curve?
02564    else if(namedCurve == TLS_EC_CURVE_BRAINPOOLP512R1)
02565       return BRAINPOOLP512R1_CURVE;
02566 #endif
02567    //Unknown identifier?
02568    else
02569       return NULL;
02570 #else
02571    //ECC not supported
02572    return NULL;
02573 #endif
02574 }
02575 
02576 
02577 /**
02578  * @brief Get the named curve that matches the specified OID
02579  * @param[in] oid Object identifier
02580  * @param[in] length OID length
02581  * @return Named curve
02582  **/
02583 
02584 TlsEcNamedCurve tlsGetNamedCurve(const uint8_t *oid, size_t length)
02585 {
02586 #if (TLS_ECDSA_SIGN_SUPPORT == ENABLED || TLS_ECDHE_ECDSA_SUPPORT == ENABLED)
02587    //Make sure the object identifier is valid
02588    if(oid == NULL)
02589       return TLS_EC_CURVE_NONE;
02590 #if (TLS_SECP160K1_SUPPORT == ENABLED)
02591    //secp160k1 elliptic curve?
02592    else if(!oidComp(oid, length, SECP160K1_OID, sizeof(SECP160K1_OID)))
02593       return TLS_EC_CURVE_SECP160K1;
02594 #endif
02595 #if (TLS_SECP160R1_SUPPORT == ENABLED)
02596    //secp160r1 elliptic curve?
02597    else if(!oidComp(oid, length, SECP160R1_OID, sizeof(SECP160R1_OID)))
02598       return TLS_EC_CURVE_SECP160R1;
02599 #endif
02600 #if (TLS_SECP160R2_SUPPORT == ENABLED)
02601    //secp160r2 elliptic curve?
02602    else if(!oidComp(oid, length, SECP160R2_OID, sizeof(SECP160R2_OID)))
02603       return TLS_EC_CURVE_SECP160R2;
02604 #endif
02605 #if (TLS_SECP192K1_SUPPORT == ENABLED)
02606    //secp192k1 elliptic curve?
02607    else if(!oidComp(oid, length, SECP192K1_OID, sizeof(SECP192K1_OID)))
02608       return TLS_EC_CURVE_SECP192K1;
02609 #endif
02610 #if (TLS_SECP192R1_SUPPORT == ENABLED)
02611    //secp192r1 elliptic curve?
02612    else if(!oidComp(oid, length, SECP192R1_OID, sizeof(SECP192R1_OID)))
02613       return TLS_EC_CURVE_SECP192R1;
02614 #endif
02615 #if (TLS_SECP224K1_SUPPORT == ENABLED)
02616    //secp224k1 elliptic curve?
02617    else if(!oidComp(oid, length, SECP224K1_OID, sizeof(SECP224K1_OID)))
02618       return TLS_EC_CURVE_SECP224K1;
02619 #endif
02620 #if (TLS_SECP224R1_SUPPORT == ENABLED)
02621    //secp224r1 elliptic curve?
02622    else if(!oidComp(oid, length, SECP224R1_OID, sizeof(SECP224R1_OID)))
02623       return TLS_EC_CURVE_SECP224R1;
02624 #endif
02625 #if (TLS_SECP256K1_SUPPORT == ENABLED)
02626    //secp256k1 elliptic curve?
02627    else if(!oidComp(oid, length, SECP256K1_OID, sizeof(SECP256K1_OID)))
02628       return TLS_EC_CURVE_SECP256K1;
02629 #endif
02630 #if (TLS_SECP256R1_SUPPORT == ENABLED)
02631    //secp256r1 elliptic curve?
02632    else if(!oidComp(oid, length, SECP256R1_OID, sizeof(SECP256R1_OID)))
02633       return TLS_EC_CURVE_SECP256R1;
02634 #endif
02635 #if (TLS_SECP384R1_SUPPORT == ENABLED)
02636    //secp384r1 elliptic curve?
02637    else if(!oidComp(oid, length, SECP384R1_OID, sizeof(SECP384R1_OID)))
02638       return TLS_EC_CURVE_SECP384R1;
02639 #endif
02640 #if (TLS_SECP521R1_SUPPORT == ENABLED)
02641    //secp521r1 elliptic curve?
02642    else if(!oidComp(oid, length, SECP521R1_OID, sizeof(SECP521R1_OID)))
02643       return TLS_EC_CURVE_SECP521R1;
02644 #endif
02645 #if (TLS_BRAINPOOLP256R1_SUPPORT == ENABLED)
02646    //brainpoolP256r1 elliptic curve?
02647    else if(!oidComp(oid, length, BRAINPOOLP256R1_OID, sizeof(BRAINPOOLP256R1_OID)))
02648       return TLS_EC_CURVE_BRAINPOOLP256R1;
02649 #endif
02650 #if (TLS_BRAINPOOLP384R1_SUPPORT == ENABLED)
02651    //brainpoolP384r1 elliptic curve?
02652    else if(!oidComp(oid, length, BRAINPOOLP384R1_OID, sizeof(BRAINPOOLP384R1_OID)))
02653       return TLS_EC_CURVE_BRAINPOOLP384R1;
02654 #endif
02655 #if (TLS_BRAINPOOLP512R1_SUPPORT == ENABLED)
02656    //brainpoolP512r1 elliptic curve?
02657    else if(!oidComp(oid, length, BRAINPOOLP512R1_OID, sizeof(BRAINPOOLP512R1_OID)))
02658       return TLS_EC_CURVE_BRAINPOOLP512R1;
02659 #endif
02660    //Unknown identifier?
02661    else
02662       return TLS_EC_CURVE_NONE;
02663 #else
02664    //ECC not supported
02665    return TLS_EC_CURVE_NONE;
02666 #endif
02667 }
02668 
02669 #endif
02670