Webserver+3d print

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers tls_client_misc.c Source File

tls_client_misc.c

Go to the documentation of this file.
00001 /**
00002  * @file tls_client_misc.c
00003  * @brief Helper functions (TLS client)
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_client.h"
00037 #include "tls_client_misc.h"
00038 #include "tls_common.h"
00039 #include "tls_record.h"
00040 #include "tls_cache.h"
00041 #include "tls_misc.h"
00042 #include "debug.h"
00043 
00044 //Check SSL library configuration
00045 #if (TLS_SUPPORT == ENABLED && TLS_CLIENT_SUPPORT == ENABLED)
00046 
00047 
00048 /**
00049  * @brief Format PSK identity
00050  * @param[in] context Pointer to the TLS context
00051  * @param[in] p Output stream where to write the PSK identity hint
00052  * @param[out] written Total number of bytes that have been written
00053  * @return Error code
00054  **/
00055 
00056 error_t tlsFormatPskIdentity(TlsContext *context,
00057    uint8_t *p, size_t *written)
00058 {
00059    size_t n;
00060    TlsPskIdentity *pskIdentity;
00061 
00062    //Point to the PSK identity
00063    pskIdentity = (TlsPskIdentity *) p;
00064 
00065    //Initialize length field
00066    n = 0;
00067 
00068 #if (TLS_PSK_SUPPORT == ENABLED || TLS_RSA_PSK_SUPPORT == ENABLED || \
00069    TLS_DHE_PSK_SUPPORT == ENABLED || TLS_ECDHE_PSK_SUPPORT == ENABLED)
00070    //Any registered callback?
00071    if(context->pskCallback != NULL)
00072    {
00073       error_t error;
00074 
00075       //Invoke user callback function
00076       if(context->pskIdentityHint != NULL)
00077          error = context->pskCallback(context, context->pskIdentityHint);
00078       else
00079          error = context->pskCallback(context, "");
00080 
00081       //Any error to report?
00082       if(error)
00083          return ERROR_UNKNOWN_IDENTITY;
00084    }
00085 
00086    //Any PSK identity defined?
00087    if(context->pskIdentity != NULL)
00088    {
00089       //Determine the length of the PSK identity
00090       n = strlen(context->pskIdentity);
00091       //Copy PSK identity
00092       memcpy(pskIdentity->value, context->pskIdentity, n);
00093    }
00094 #endif
00095 
00096    //The PSK identity is preceded by a 2-byte length field
00097    pskIdentity->length = htons(n);
00098 
00099    //Total number of bytes that have been written
00100    *written = sizeof(TlsPskIdentity) + n;
00101 
00102    //Successful processing
00103    return NO_ERROR;
00104 }
00105 
00106 
00107 /**
00108  * @brief Format client's key exchange parameters
00109  * @param[in] context Pointer to the TLS context
00110  * @param[in] p Output stream where to write the PSK identity hint
00111  * @param[out] written Total number of bytes that have been written
00112  * @return Error code
00113  **/
00114 
00115 error_t tlsFormatClientKeyParams(TlsContext *context,
00116    uint8_t *p, size_t *written)
00117 {
00118 #if (TLS_RSA_SUPPORT == ENABLED || TLS_RSA_PSK_SUPPORT == ENABLED)
00119    //RSA key exchange method?
00120    if(context->keyExchMethod == TLS_KEY_EXCH_RSA ||
00121       context->keyExchMethod == TLS_KEY_EXCH_RSA_PSK)
00122    {
00123       error_t error;
00124       size_t n;
00125 
00126       //Sanity check
00127       if(TLS_MAX_PREMASTER_SECRET_SIZE < 48)
00128          return ERROR_BUFFER_OVERFLOW;
00129 
00130       //If RSA is being used for key agreement and authentication, the
00131       //client generates a 48-byte premaster secret
00132       context->premasterSecretLen = 48;
00133 
00134       //The first 2 bytes code the latest version supported by the client
00135       STORE16BE(TLS_MAX_VERSION, context->premasterSecret);
00136 
00137       //The last 46 bytes contain securely-generated random bytes
00138       error = context->prngAlgo->read(context->prngContext,
00139          context->premasterSecret + 2, 46);
00140       //Any error to report?
00141       if(error)
00142          return error;
00143 
00144       //The RSA-encrypted premaster secret in a ClientKeyExchange is preceded by
00145       //two length bytes. SSL 3.0 implementations do not include these bytes
00146       if(context->version > SSL_VERSION_3_0)
00147       {
00148          //Encrypt the premaster secret using the server public key
00149          error = rsaesPkcs1v15Encrypt(context->prngAlgo, context->prngContext,
00150             &context->peerRsaPublicKey, context->premasterSecret, 48, p + 2, &n);
00151          //RSA encryption failed?
00152          if(error)
00153             return error;
00154 
00155          //Write the length field
00156          STORE16BE(n, p);
00157 
00158          //Length of the resulting octet string
00159          n += 2;
00160       }
00161       else
00162       {
00163          //Encrypt the premaster secret using the server public key
00164          error = rsaesPkcs1v15Encrypt(context->prngAlgo, context->prngContext,
00165             &context->peerRsaPublicKey, context->premasterSecret, 48, p, &n);
00166          //RSA encryption failed?
00167          if(error)
00168             return error;
00169       }
00170 
00171       //Total number of bytes that have been written
00172       *written = n;
00173    }
00174    else
00175 #endif
00176 #if (TLS_DH_ANON_SUPPORT == ENABLED || TLS_DHE_RSA_SUPPORT == ENABLED || \
00177    TLS_DHE_DSS_SUPPORT == ENABLED || TLS_DHE_PSK_SUPPORT == ENABLED)
00178    //Diffie-Hellman key exchange method?
00179    if(context->keyExchMethod == TLS_KEY_EXCH_DH_ANON ||
00180       context->keyExchMethod == TLS_KEY_EXCH_DHE_RSA ||
00181       context->keyExchMethod == TLS_KEY_EXCH_DHE_DSS ||
00182       context->keyExchMethod == TLS_KEY_EXCH_DHE_PSK)
00183    {
00184       error_t error;
00185       size_t n;
00186 
00187       //Generate an ephemeral key pair
00188       error = dhGenerateKeyPair(&context->dhContext,
00189          context->prngAlgo, context->prngContext);
00190       //Any error to report?
00191       if(error)
00192          return error;
00193 
00194       //Encode the client's public value to an opaque vector
00195       error = tlsWriteMpi(&context->dhContext.ya, p, &n);
00196       //Any error to report?
00197       if(error)
00198          return error;
00199 
00200       //Total number of bytes that have been written
00201       *written = n;
00202 
00203       //Calculate the negotiated key Z
00204       error = dhComputeSharedSecret(&context->dhContext, context->premasterSecret,
00205          TLS_MAX_PREMASTER_SECRET_SIZE, &context->premasterSecretLen);
00206       //Any error to report?
00207       if(error)
00208          return error;
00209 
00210       //Leading bytes of Z that contain all zero bits are stripped before
00211       //it is used as the premaster secret (RFC 4346, section 8.2.1)
00212       for(n = 0; n < context->premasterSecretLen; n++)
00213       {
00214          if(context->premasterSecret[n] != 0x00)
00215             break;
00216       }
00217 
00218       //Any leading zero bytes?
00219       if(n > 0)
00220       {
00221          //Strip leading zero bytes from the negotiated key
00222          memmove(context->premasterSecret, context->premasterSecret + n,
00223             context->premasterSecretLen - n);
00224 
00225          //Adjust the length of the premaster secret
00226          context->premasterSecretLen -= n;
00227       }
00228    }
00229    else
00230 #endif
00231 #if (TLS_ECDH_ANON_SUPPORT == ENABLED || TLS_ECDHE_RSA_SUPPORT == ENABLED || \
00232    TLS_ECDHE_ECDSA_SUPPORT == ENABLED || TLS_ECDHE_PSK_SUPPORT == ENABLED)
00233    //ECDH key exchange method?
00234    if(context->keyExchMethod == TLS_KEY_EXCH_ECDH_ANON ||
00235       context->keyExchMethod == TLS_KEY_EXCH_ECDHE_RSA ||
00236       context->keyExchMethod == TLS_KEY_EXCH_ECDHE_ECDSA ||
00237       context->keyExchMethod == TLS_KEY_EXCH_ECDHE_PSK)
00238    {
00239       error_t error;
00240       size_t n;
00241 
00242       //Generate an ephemeral key pair
00243       error = ecdhGenerateKeyPair(&context->ecdhContext,
00244          context->prngAlgo, context->prngContext);
00245       //Any error to report?
00246       if(error)
00247          return error;
00248 
00249       //Encode the client's public key to an opaque vector
00250       error = tlsWriteEcPoint(&context->ecdhContext.params,
00251          &context->ecdhContext.qa, p, &n);
00252       //Any error to report?
00253       if(error)
00254          return error;
00255 
00256       //Total number of bytes that have been written
00257       *written = n;
00258 
00259       //Calculate the negotiated key Z
00260       error = ecdhComputeSharedSecret(&context->ecdhContext, context->premasterSecret,
00261          TLS_MAX_PREMASTER_SECRET_SIZE, &context->premasterSecretLen);
00262       //Any error to report?
00263       if(error)
00264          return error;
00265    }
00266    else
00267 #endif
00268    //Invalid key exchange method?
00269    {
00270       //The specified key exchange method is not supported
00271       return ERROR_UNSUPPORTED_KEY_EXCH_METHOD;
00272    }
00273 
00274    //Successful processing
00275    return NO_ERROR;
00276 }
00277 
00278 
00279 /**
00280  * @brief Parse PSK identity hint
00281  * @param[in] context Pointer to the TLS context
00282  * @param[in] p Input stream where to read the PSK identity hint
00283  * @param[in] length Number of bytes available in the input stream
00284  * @param[out] consumed Total number of bytes that have been consumed
00285  * @return Error code
00286  **/
00287 
00288 error_t tlsParsePskIdentityHint(TlsContext *context,
00289     const uint8_t *p, size_t length, size_t *consumed)
00290 {
00291    size_t n;
00292    TlsPskIdentityHint *pskIdentityHint;
00293 
00294    //Malformed ServerKeyExchange message?
00295    if(length < sizeof(TlsPskIdentityHint))
00296       return ERROR_DECODING_FAILED;
00297 
00298    //Point to the PSK identity hint
00299    pskIdentityHint = (TlsPskIdentityHint *) p;
00300 
00301    //Retrieve the length of the PSK identity hint
00302    n = ntohs(pskIdentityHint->length);
00303 
00304    //Make sure the length field is valid
00305    if(length < (sizeof(TlsPskIdentityHint) + n))
00306       return ERROR_DECODING_FAILED;
00307 
00308 #if (TLS_PSK_SUPPORT == ENABLED || TLS_RSA_PSK_SUPPORT == ENABLED || \
00309    TLS_DHE_PSK_SUPPORT == ENABLED || TLS_ECDHE_PSK_SUPPORT == ENABLED)
00310    //Check whether the PSK identity hint has already been configured
00311    if(context->pskIdentityHint != NULL)
00312    {
00313       //Release memory
00314       tlsFreeMem(context->pskIdentityHint);
00315       context->pskIdentityHint = NULL;
00316    }
00317 
00318    //The PSK identity hint is optional
00319    if(n > 0)
00320    {
00321       //Allocate a memory block to hold the PSK identity hint
00322       context->pskIdentityHint = tlsAllocMem(n + 1);
00323       //Failed to allocate memory?
00324       if(context->pskIdentityHint == NULL)
00325          return ERROR_OUT_OF_MEMORY;
00326 
00327       //Save the PSK identity hint
00328       memcpy(context->pskIdentityHint, pskIdentityHint->value, n);
00329       //Properly terminate the string
00330       context->pskIdentityHint[n] = '\0';
00331    }
00332 #endif
00333 
00334    //Total number of bytes that have been consumed
00335    *consumed = sizeof(TlsPskIdentityHint) + n;
00336 
00337    //Successful processing
00338    return NO_ERROR;
00339 }
00340 
00341 
00342 /**
00343  * @brief Parse server's key exchange parameters
00344  * @param[in] context Pointer to the TLS context
00345  * @param[in] p Input stream where to read the server's key exchange parameters
00346  * @param[in] length Number of bytes available in the input stream
00347  * @param[out] consumed Total number of bytes that have been consumed
00348  * @return Error code
00349  **/
00350 
00351 error_t tlsParseServerKeyParams(TlsContext *context,
00352     const uint8_t *p, size_t length, size_t *consumed)
00353 {
00354    error_t error;
00355    const uint8_t *params;
00356 
00357    //Initialize status code
00358    error = NO_ERROR;
00359 
00360    //Point to the server's key exchange parameters
00361    params = p;
00362 
00363 #if (TLS_DH_ANON_SUPPORT == ENABLED || TLS_DHE_RSA_SUPPORT == ENABLED || \
00364    TLS_DHE_DSS_SUPPORT == ENABLED || TLS_DHE_PSK_SUPPORT == ENABLED)
00365    //Diffie-Hellman key exchange method?
00366    if(context->keyExchMethod == TLS_KEY_EXCH_DH_ANON ||
00367       context->keyExchMethod == TLS_KEY_EXCH_DHE_RSA ||
00368       context->keyExchMethod == TLS_KEY_EXCH_DHE_DSS ||
00369       context->keyExchMethod == TLS_KEY_EXCH_DHE_PSK)
00370    {
00371       uint_t k;
00372       size_t n;
00373 
00374       //Convert the prime modulus to a multiple precision integer
00375       error = tlsReadMpi(&context->dhContext.params.p, p, length, &n);
00376 
00377       //Check status code
00378       if(!error)
00379       {
00380          //Get the length of the prime modulus, in bits
00381          k = mpiGetBitLength(&context->dhContext.params.p);
00382 
00383          //Make sure the prime modulus is acceptable
00384          if(k < TLS_MIN_DH_MODULUS_SIZE || k > TLS_MAX_DH_MODULUS_SIZE)
00385             error = ERROR_ILLEGAL_PARAMETER;
00386       }
00387 
00388       //Check status code
00389       if(!error)
00390       {
00391          //Advance data pointer
00392          p += n;
00393          //Remaining bytes to process
00394          length -= n;
00395 
00396          //Convert the generator to a multiple precision integer
00397          error = tlsReadMpi(&context->dhContext.params.g, p, length, &n);
00398       }
00399 
00400       //Check status code
00401       if(!error)
00402       {
00403          //Advance data pointer
00404          p += n;
00405          //Remaining bytes to process
00406          length -= n;
00407 
00408          //Convert the server's public value to a multiple precision integer
00409          error = tlsReadMpi(&context->dhContext.yb, p, length, &n);
00410       }
00411 
00412       //Check status code
00413       if(!error)
00414       {
00415          //Advance data pointer
00416          p += n;
00417          //Remaining bytes to process
00418          length -= n;
00419 
00420          //Verify peer's public value
00421          error = dhCheckPublicKey(&context->dhContext.params,
00422             &context->dhContext.yb);
00423       }
00424 
00425       //Check status code
00426       if(!error)
00427       {
00428          //Debug message
00429          TRACE_DEBUG("Diffie-Hellman parameters:\r\n");
00430          TRACE_DEBUG("  Prime modulus:\r\n");
00431          TRACE_DEBUG_MPI("    ", &context->dhContext.params.p);
00432          TRACE_DEBUG("  Generator:\r\n");
00433          TRACE_DEBUG_MPI("    ", &context->dhContext.params.g);
00434          TRACE_DEBUG("  Server public value:\r\n");
00435          TRACE_DEBUG_MPI("    ", &context->dhContext.yb);
00436       }
00437    }
00438    else
00439 #endif
00440 #if (TLS_ECDH_ANON_SUPPORT == ENABLED || TLS_ECDHE_RSA_SUPPORT == ENABLED || \
00441    TLS_ECDHE_ECDSA_SUPPORT == ENABLED || TLS_ECDHE_PSK_SUPPORT == ENABLED)
00442    //ECDH key exchange method?
00443    if(context->keyExchMethod == TLS_KEY_EXCH_ECDH_ANON ||
00444       context->keyExchMethod == TLS_KEY_EXCH_ECDHE_RSA ||
00445       context->keyExchMethod == TLS_KEY_EXCH_ECDHE_ECDSA ||
00446       context->keyExchMethod == TLS_KEY_EXCH_ECDHE_PSK)
00447    {
00448       size_t n;
00449       uint8_t curveType;
00450       uint16_t namedCurve;
00451       const EcCurveInfo *curveInfo;
00452 
00453       //Malformed ServerKeyExchange message?
00454       if(length < sizeof(curveType))
00455          error = ERROR_DECODING_FAILED;
00456 
00457       //Check status code
00458       if(!error)
00459       {
00460          //Retrieve the type of the elliptic curve domain parameters
00461          curveType = *p;
00462 
00463          //Advance data pointer
00464          p += sizeof(curveType);
00465          //Remaining bytes to process
00466          length -= sizeof(curveType);
00467 
00468          //Only named curves are supported
00469          if(curveType != TLS_EC_CURVE_TYPE_NAMED_CURVE)
00470             error = ERROR_ILLEGAL_PARAMETER;
00471       }
00472 
00473       //Check status code
00474       if(!error)
00475       {
00476          //Malformed ServerKeyExchange message?
00477          if(length < sizeof(namedCurve))
00478             error = ERROR_DECODING_FAILED;
00479       }
00480 
00481       //Check status code
00482       if(!error)
00483       {
00484          //Get elliptic curve identifier
00485          namedCurve = LOAD16BE(p);
00486 
00487          //Advance data pointer
00488          p += sizeof(namedCurve);
00489          //Remaining bytes to process
00490          length -= sizeof(namedCurve);
00491 
00492          //Retrieve the corresponding EC domain parameters
00493          curveInfo = tlsGetCurveInfo(namedCurve);
00494 
00495          //Make sure the elliptic curve is supported
00496          if(curveInfo == NULL)
00497             error = ERROR_ILLEGAL_PARAMETER;
00498       }
00499 
00500       //Check status code
00501       if(!error)
00502       {
00503          //Load EC domain parameters
00504          error = ecLoadDomainParameters(&context->ecdhContext.params,
00505             curveInfo);
00506       }
00507 
00508       //Check status code
00509       if(!error)
00510       {
00511          //Read server's public key
00512          error = tlsReadEcPoint(&context->ecdhContext.params,
00513             &context->ecdhContext.qb, p, length, &n);
00514       }
00515 
00516       //Check status code
00517       if(!error)
00518       {
00519          //Advance data pointer
00520          p += n;
00521          //Remaining bytes to process
00522          length -= n;
00523 
00524          //Verify peer's public key
00525          error = ecdhCheckPublicKey(&context->ecdhContext.params, &context->ecdhContext.qb);
00526       }
00527 
00528       //Check status code
00529       if(!error)
00530       {
00531          //Debug message
00532          TRACE_DEBUG("  Server public key X:\r\n");
00533          TRACE_DEBUG_MPI("    ", &context->ecdhContext.qb.x);
00534          TRACE_DEBUG("  Server public key Y:\r\n");
00535          TRACE_DEBUG_MPI("    ", &context->ecdhContext.qb.y);
00536       }
00537    }
00538    else
00539 #endif
00540    //Invalid key exchange method?
00541    {
00542       //It is not legal to send the ServerKeyExchange message when a key
00543       //exchange method other than DHE_DSS, DHE_RSA, DH_anon, ECDHE_RSA,
00544       //ECDHE_ECDSA or ECDH_anon is selected
00545       error = ERROR_UNEXPECTED_MESSAGE;
00546    }
00547 
00548    //Total number of bytes that have been consumed
00549    *consumed = p - params;
00550 
00551    //Return status code
00552    return error;
00553 }
00554 
00555 
00556 /**
00557  * @brief Verify signature over the server's key exchange parameters
00558  * @param[in] context Pointer to the TLS context
00559  * @param[in] p Input stream where to read the signature
00560  * @param[in] length Number of bytes available in the input stream
00561  * @param[in] params Pointer to the server's key exchange parameters
00562  * @param[in] paramsLen Length of the server's key exchange parameters
00563  * @param[out] consumed Total number of bytes that have been consumed
00564  * @return Error code
00565  **/
00566 
00567 error_t tlsVerifyServerKeySignature(TlsContext *context, const uint8_t *p,
00568    size_t length, const uint8_t *params, size_t paramsLen, size_t *consumed)
00569 {
00570    error_t error;
00571 
00572    //Initialize status code
00573    error = NO_ERROR;
00574 
00575 #if (TLS_MAX_VERSION >= SSL_VERSION_3_0 && TLS_MIN_VERSION <= TLS_VERSION_1_1)
00576    //SSL 3.0, TLS 1.0 or TLS 1.1 currently selected?
00577    if(context->version <= TLS_VERSION_1_1)
00578    {
00579       TlsDigitalSignature *signature;
00580 
00581       //Point to the digitally-signed element
00582       signature = (TlsDigitalSignature *) p;
00583 
00584       //Check the length of the digitally-signed element
00585       if(length < sizeof(TlsDigitalSignature))
00586          return ERROR_DECODING_FAILED;
00587       if(length < (sizeof(TlsDigitalSignature) + ntohs(signature->length)))
00588          return ERROR_DECODING_FAILED;
00589 
00590 #if (TLS_DHE_RSA_SUPPORT == ENABLED || TLS_ECDHE_RSA_SUPPORT == ENABLED)
00591       //Check whether DHE_RSA or ECDHE_RSA key exchange method is currently used
00592       if(context->keyExchMethod == TLS_KEY_EXCH_DHE_RSA ||
00593          context->keyExchMethod == TLS_KEY_EXCH_ECDHE_RSA)
00594       {
00595          Md5Context *md5Context;
00596          Sha1Context *sha1Context;
00597 
00598          //Allocate a memory buffer to hold the MD5 context
00599          md5Context = tlsAllocMem(sizeof(Md5Context));
00600 
00601          //Successful memory allocation?
00602          if(md5Context != NULL)
00603          {
00604             //Compute MD5(ClientHello.random + ServerHello.random + ServerDhParams)
00605             md5Init(md5Context);
00606             md5Update(md5Context, context->random, 64);
00607             md5Update(md5Context, params, paramsLen);
00608             md5Final(md5Context, context->verifyData);
00609 
00610             //Release previously allocated memory
00611             tlsFreeMem(md5Context);
00612          }
00613          else
00614          {
00615             //Failed to allocate memory
00616             error = ERROR_OUT_OF_MEMORY;
00617          }
00618 
00619          //Check status code
00620          if(!error)
00621          {
00622             //Allocate a memory buffer to hold the SHA-1 context
00623             sha1Context = tlsAllocMem(sizeof(Sha1Context));
00624 
00625             //Successful memory allocation?
00626             if(sha1Context != NULL)
00627             {
00628                //Compute SHA(ClientHello.random + ServerHello.random + ServerDhParams)
00629                sha1Init(sha1Context);
00630                sha1Update(sha1Context, context->random, 64);
00631                sha1Update(sha1Context, params, paramsLen);
00632                sha1Final(sha1Context, context->verifyData + MD5_DIGEST_SIZE);
00633 
00634                //Release previously allocated memory
00635                tlsFreeMem(sha1Context);
00636             }
00637             else
00638             {
00639                //Failed to allocate memory
00640                error = ERROR_OUT_OF_MEMORY;
00641             }
00642          }
00643 
00644          //Check status code
00645          if(!error)
00646          {
00647             //RSA signature verification
00648             error = tlsVerifyRsaSignature(&context->peerRsaPublicKey,
00649                context->verifyData, signature->value, ntohs(signature->length));
00650          }
00651       }
00652       else
00653 #endif
00654 #if (TLS_DHE_DSS_SUPPORT == ENABLED)
00655       //Check whether DHE_DSS key exchange method is currently used
00656       if(context->keyExchMethod == TLS_KEY_EXCH_DHE_DSS)
00657       {
00658          Sha1Context *sha1Context;
00659 
00660          //Allocate a memory buffer to hold the SHA-1 context
00661          sha1Context = tlsAllocMem(sizeof(Sha1Context));
00662 
00663          //Successful memory allocation?
00664          if(sha1Context != NULL)
00665          {
00666             //Compute SHA(ClientHello.random + ServerHello.random + ServerDhParams)
00667             sha1Init(sha1Context);
00668             sha1Update(sha1Context, context->random, 64);
00669             sha1Update(sha1Context, params, paramsLen);
00670             sha1Final(sha1Context, context->verifyData);
00671 
00672             //Release previously allocated memory
00673             tlsFreeMem(sha1Context);
00674          }
00675          else
00676          {
00677             //Failed to allocate memory
00678             error = ERROR_OUT_OF_MEMORY;
00679          }
00680 
00681          //Check status code
00682          if(!error)
00683          {
00684             //DSA signature verification
00685             error = tlsVerifyDsaSignature(&context->peerDsaPublicKey, context->verifyData,
00686                SHA1_DIGEST_SIZE, signature->value, ntohs(signature->length));
00687          }
00688       }
00689       else
00690 #endif
00691 #if (TLS_ECDHE_ECDSA_SUPPORT == ENABLED)
00692       //Check whether ECDHE_ECDSA key exchange method is currently used
00693       if(context->keyExchMethod == TLS_KEY_EXCH_ECDHE_ECDSA)
00694       {
00695          Sha1Context *sha1Context;
00696 
00697          //Allocate a memory buffer to hold the SHA-1 context
00698          sha1Context = tlsAllocMem(sizeof(Sha1Context));
00699 
00700          //Successful memory allocation?
00701          if(sha1Context != NULL)
00702          {
00703             //Compute SHA(ClientHello.random + ServerHello.random + ServerDhParams)
00704             sha1Init(sha1Context);
00705             sha1Update(sha1Context, context->random, 64);
00706             sha1Update(sha1Context, params, paramsLen);
00707             sha1Final(sha1Context, context->verifyData);
00708 
00709             //Release previously allocated memory
00710             tlsFreeMem(sha1Context);
00711          }
00712 
00713          //Check status code
00714          if(!error)
00715          {
00716             //ECDSA signature verification
00717             error = tlsVerifyEcdsaSignature(&context->peerEcParams,
00718                &context->peerEcPublicKey, context->verifyData,
00719                SHA1_DIGEST_SIZE, signature->value, ntohs(signature->length));
00720          }
00721       }
00722       else
00723 #endif
00724       //Invalid signature algorithm?
00725       {
00726          //Report an error
00727          error = ERROR_UNSUPPORTED_SIGNATURE_ALGO;
00728       }
00729 
00730       //Total number of bytes that have been consumed
00731       *consumed = sizeof(TlsDigitalSignature) + ntohs(signature->length);
00732    }
00733    else
00734 #endif
00735 #if (TLS_MAX_VERSION >= TLS_VERSION_1_2 && TLS_MIN_VERSION <= TLS_VERSION_1_2)
00736    //TLS 1.2 currently selected?
00737    if(context->version == TLS_VERSION_1_2)
00738    {
00739       TlsDigitalSignature2 *signature;
00740       const HashAlgo *hashAlgo;
00741       HashContext *hashContext;
00742 
00743       //Point to the digitally-signed element
00744       signature = (TlsDigitalSignature2 *) p;
00745 
00746       //Check the length of the digitally-signed element
00747       if(length < sizeof(TlsDigitalSignature2))
00748          return ERROR_DECODING_FAILED;
00749       if(length < (sizeof(TlsDigitalSignature2) + ntohs(signature->length)))
00750          return ERROR_DECODING_FAILED;
00751 
00752       //Retrieve the hash algorithm used for signing
00753       hashAlgo = tlsGetHashAlgo(signature->algorithm.hash);
00754 
00755       //Make sure the hash algorithm is supported
00756       if(hashAlgo != NULL)
00757       {
00758          //Allocate a memory buffer to hold the hash context
00759          hashContext = tlsAllocMem(hashAlgo->contextSize);
00760 
00761          //Successful memory allocation?
00762          if(hashContext != NULL)
00763          {
00764             //Compute SHA(ClientHello.random + ServerHello.random + ServerDhParams)
00765             hashAlgo->init(hashContext);
00766             hashAlgo->update(hashContext, context->random, 64);
00767             hashAlgo->update(hashContext, params, paramsLen);
00768             hashAlgo->final(hashContext, NULL);
00769 
00770 #if (TLS_DHE_RSA_SUPPORT == ENABLED || TLS_ECDHE_RSA_SUPPORT == ENABLED)
00771             //Check whether DHE_RSA or ECDHE_RSA key exchange method is currently used
00772             if((context->keyExchMethod == TLS_KEY_EXCH_DHE_RSA ||
00773                context->keyExchMethod == TLS_KEY_EXCH_ECDHE_RSA) &&
00774                signature->algorithm.signature == TLS_SIGN_ALGO_RSA)
00775             {
00776                //Use the signature verification algorithm defined in PKCS #1 v1.5
00777                error = rsassaPkcs1v15Verify(&context->peerRsaPublicKey, hashAlgo,
00778                   hashContext->digest, signature->value, ntohs(signature->length));
00779             }
00780             else
00781 #endif
00782 #if (TLS_DHE_DSS_SUPPORT == ENABLED)
00783             //Check whether DHE_DSS key exchange method is currently used
00784             if(context->keyExchMethod == TLS_KEY_EXCH_DHE_DSS &&
00785                signature->algorithm.signature == TLS_SIGN_ALGO_DSA)
00786             {
00787                //DSA signature verification
00788                error = tlsVerifyDsaSignature(&context->peerDsaPublicKey, hashContext->digest,
00789                   hashAlgo->digestSize, signature->value, ntohs(signature->length));
00790             }
00791             else
00792 #endif
00793 #if (TLS_ECDHE_ECDSA_SUPPORT == ENABLED)
00794             //Check whether DHE_ECDSA key exchange method is currently used
00795             if(context->keyExchMethod == TLS_KEY_EXCH_ECDHE_ECDSA &&
00796                signature->algorithm.signature == TLS_SIGN_ALGO_ECDSA)
00797             {
00798                //ECDSA signature verification
00799                error = tlsVerifyEcdsaSignature(&context->peerEcParams, &context->peerEcPublicKey,
00800                   hashContext->digest, hashAlgo->digestSize, signature->value, ntohs(signature->length));
00801             }
00802             else
00803 #endif
00804             //Invalid signature algorithm?
00805             {
00806                //Report an error
00807                error = ERROR_UNSUPPORTED_SIGNATURE_ALGO;
00808             }
00809 
00810             //Release previously allocated memory
00811             tlsFreeMem(hashContext);
00812          }
00813          else
00814          {
00815             //Failed to allocate memory
00816             error = ERROR_OUT_OF_MEMORY;
00817          }
00818       }
00819       else
00820       {
00821          //Hash algorithm not supported
00822          error = ERROR_INVALID_SIGNATURE;
00823       }
00824 
00825       //Total number of bytes that have been consumed
00826       *consumed = sizeof(TlsDigitalSignature2) + ntohs(signature->length);
00827    }
00828    else
00829 #endif
00830    {
00831       //The negotiated TLS version is not valid
00832       error = ERROR_INVALID_VERSION;
00833    }
00834 
00835    //Return status code
00836    return error;
00837 }
00838 
00839 #endif
00840