Webserver+3d print

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers tls_server_misc.c Source File

tls_server_misc.c

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