This is a port of cyaSSL 2.7.0.

Dependents:   CyaSSL_DTLS_Cellular CyaSSL_DTLS_Ethernet

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers tls.c Source File

tls.c

00001 /* tls.c
00002  *
00003  * Copyright (C) 2006-2013 wolfSSL Inc.
00004  *
00005  * This file is part of CyaSSL.
00006  *
00007  * CyaSSL is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version.
00011  *
00012  * CyaSSL is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
00020  */
00021 
00022 #ifdef HAVE_CONFIG_H
00023     #include <config.h>
00024 #endif
00025 
00026 #include <cyassl/ctaocrypt/settings.h>
00027 
00028 #include <cyassl/ssl.h>
00029 #include <cyassl/internal.h>
00030 #include <cyassl/ctaoerror.h>
00031 #include <cyassl/ctaocrypt/hmac.h>
00032 
00033 
00034 
00035 #ifndef NO_TLS
00036 
00037 
00038 #ifndef min
00039 
00040     static INLINE word32 min(word32 a, word32 b)
00041     {
00042         return a > b ? b : a;
00043     }
00044 
00045 #endif /* min */
00046 
00047 
00048 #ifdef CYASSL_SHA384
00049     #define PHASH_MAX_DIGEST_SIZE SHA384_DIGEST_SIZE
00050 #else
00051     #define PHASH_MAX_DIGEST_SIZE SHA256_DIGEST_SIZE
00052 #endif
00053 
00054 /* compute p_hash for MD5, SHA-1, SHA-256, or SHA-384 for TLSv1 PRF */
00055 static void p_hash(byte* result, word32 resLen, const byte* secret,
00056                    word32 secLen, const byte* seed, word32 seedLen, int hash)
00057 {
00058     word32   len = PHASH_MAX_DIGEST_SIZE;
00059     word32   times;
00060     word32   lastLen;
00061     word32   lastTime;
00062     word32   i;
00063     word32   idx = 0;
00064     byte     previous[PHASH_MAX_DIGEST_SIZE];  /* max size */
00065     byte     current[PHASH_MAX_DIGEST_SIZE];   /* max size */
00066 
00067     Hmac hmac;
00068 
00069     switch (hash) {
00070         #ifndef NO_MD5
00071         case md5_mac:
00072         {
00073             len = MD5_DIGEST_SIZE;
00074             hash = MD5;
00075         }
00076         break;
00077         #endif
00078         #ifndef NO_SHA256
00079         case sha256_mac:
00080         {
00081             len = SHA256_DIGEST_SIZE;
00082             hash = SHA256;
00083         }
00084         break;
00085         #endif
00086         #ifdef CYASSL_SHA384
00087         case sha384_mac:
00088         {
00089             len = SHA384_DIGEST_SIZE;
00090             hash = SHA384;
00091         }
00092         break;
00093         #endif
00094 #ifndef NO_SHA
00095         case sha_mac:
00096         default:
00097         {
00098             len = SHA_DIGEST_SIZE;
00099             hash = SHA;
00100         }
00101         break;
00102 #endif
00103     }
00104 
00105     times = resLen / len;
00106     lastLen = resLen % len;
00107     if (lastLen) times += 1;
00108     lastTime = times - 1;
00109 
00110     HmacSetKey(&hmac, hash, secret, secLen);
00111     HmacUpdate(&hmac, seed, seedLen);       /* A0 = seed */
00112     HmacFinal(&hmac, previous);             /* A1 */
00113 
00114     for (i = 0; i < times; i++) {
00115         HmacUpdate(&hmac, previous, len);
00116         HmacUpdate(&hmac, seed, seedLen);
00117         HmacFinal(&hmac, current);
00118 
00119         if ( (i == lastTime) && lastLen)
00120             XMEMCPY(&result[idx], current, min(lastLen, sizeof(current)));
00121         else {
00122             XMEMCPY(&result[idx], current, len);
00123             idx += len;
00124             HmacUpdate(&hmac, previous, len);
00125             HmacFinal(&hmac, previous);
00126         }
00127     }
00128     XMEMSET(previous, 0, sizeof previous);
00129     XMEMSET(current, 0, sizeof current);
00130     XMEMSET(&hmac, 0, sizeof hmac);
00131 }
00132 
00133 
00134 
00135 #ifndef NO_OLD_TLS
00136 
00137 /* calculate XOR for TLSv1 PRF */
00138 static INLINE void get_xor(byte *digest, word32 digLen, byte* md5, byte* sha)
00139 {
00140     word32 i;
00141 
00142     for (i = 0; i < digLen; i++) 
00143         digest[i] = md5[i] ^ sha[i];
00144 }
00145 
00146 
00147 /* compute TLSv1 PRF (pseudo random function using HMAC) */
00148 static void doPRF(byte* digest, word32 digLen, const byte* secret,word32 secLen,
00149             const byte* label, word32 labLen, const byte* seed, word32 seedLen)
00150 {
00151     word32 half = (secLen + 1) / 2;
00152 
00153     byte md5_half[MAX_PRF_HALF];        /* half is real size */
00154     byte sha_half[MAX_PRF_HALF];        /* half is real size */
00155     byte labelSeed[MAX_PRF_LABSEED];    /* labLen + seedLen is real size */
00156     byte md5_result[MAX_PRF_DIG];       /* digLen is real size */
00157     byte sha_result[MAX_PRF_DIG];       /* digLen is real size */
00158 
00159     if (half > MAX_PRF_HALF)
00160         return;
00161     if (labLen + seedLen > MAX_PRF_LABSEED)
00162         return;
00163     if (digLen > MAX_PRF_DIG)
00164         return;
00165 
00166     XMEMSET(md5_result, 0, digLen);
00167     XMEMSET(sha_result, 0, digLen);
00168     
00169     XMEMCPY(md5_half, secret, half);
00170     XMEMCPY(sha_half, secret + half - secLen % 2, half);
00171 
00172     XMEMCPY(labelSeed, label, labLen);
00173     XMEMCPY(labelSeed + labLen, seed, seedLen);
00174 
00175     p_hash(md5_result, digLen, md5_half, half, labelSeed, labLen + seedLen,
00176            md5_mac);
00177     p_hash(sha_result, digLen, sha_half, half, labelSeed, labLen + seedLen,
00178            sha_mac);
00179     get_xor(digest, digLen, md5_result, sha_result);
00180 }
00181 
00182 #endif
00183 
00184 
00185 /* Wrapper to call straight thru to p_hash in TSL 1.2 cases to remove stack
00186    use */
00187 static void PRF(byte* digest, word32 digLen, const byte* secret, word32 secLen,
00188             const byte* label, word32 labLen, const byte* seed, word32 seedLen,
00189             int useAtLeastSha256, int hash_type)
00190 {
00191     if (useAtLeastSha256) {
00192         byte labelSeed[MAX_PRF_LABSEED];    /* labLen + seedLen is real size */
00193 
00194         if (labLen + seedLen > MAX_PRF_LABSEED)
00195             return;
00196 
00197         XMEMCPY(labelSeed, label, labLen);
00198         XMEMCPY(labelSeed + labLen, seed, seedLen);
00199 
00200         /* If a cipher suite wants an algorithm better than sha256, it
00201          * should use better. */
00202         if (hash_type < sha256_mac)
00203             hash_type = sha256_mac;
00204         p_hash(digest, digLen, secret, secLen, labelSeed, labLen + seedLen,
00205                hash_type);
00206     }
00207 #ifndef NO_OLD_TLS
00208     else
00209         doPRF(digest, digLen, secret, secLen, label, labLen, seed, seedLen);
00210 #endif
00211 }
00212 
00213 
00214 #ifdef CYASSL_SHA384
00215     #define HSHASH_SZ SHA384_DIGEST_SIZE
00216 #else
00217     #define HSHASH_SZ FINISHED_SZ
00218 #endif
00219 
00220 
00221 void BuildTlsFinished(CYASSL* ssl, Hashes* hashes, const byte* sender)
00222 {
00223     const byte* side;
00224     byte        handshake_hash[HSHASH_SZ];
00225     word32      hashSz = FINISHED_SZ;
00226 
00227 #ifndef NO_OLD_TLS
00228     Md5Final(&ssl->hashMd5, handshake_hash);
00229     ShaFinal(&ssl->hashSha, &handshake_hash[MD5_DIGEST_SIZE]);
00230 #endif
00231     
00232     if (IsAtLeastTLSv1_2(ssl)) {
00233 #ifndef NO_SHA256
00234         if (ssl->specs.mac_algorithm <= sha256_mac) {
00235             Sha256Final(&ssl->hashSha256, handshake_hash);
00236             hashSz = SHA256_DIGEST_SIZE;
00237         }
00238 #endif
00239 #ifdef CYASSL_SHA384
00240         if (ssl->specs.mac_algorithm == sha384_mac) {
00241             Sha384Final(&ssl->hashSha384, handshake_hash);
00242             hashSz = SHA384_DIGEST_SIZE;
00243         }
00244 #endif
00245     }
00246    
00247     if ( XSTRNCMP((const char*)sender, (const char*)client, SIZEOF_SENDER) == 0)
00248         side = tls_client;
00249     else
00250         side = tls_server;
00251 
00252     PRF((byte*)hashes, TLS_FINISHED_SZ, ssl->arrays->masterSecret, SECRET_LEN,
00253         side, FINISHED_LABEL_SZ, handshake_hash, hashSz, IsAtLeastTLSv1_2(ssl),
00254         ssl->specs.mac_algorithm);
00255 }
00256 
00257 
00258 #ifndef NO_OLD_TLS
00259 
00260 ProtocolVersion MakeTLSv1(void)
00261 {
00262     ProtocolVersion pv;
00263     pv.major = SSLv3_MAJOR;
00264     pv.minor = TLSv1_MINOR;
00265 
00266     return pv;
00267 }
00268 
00269 
00270 ProtocolVersion MakeTLSv1_1(void)
00271 {
00272     ProtocolVersion pv;
00273     pv.major = SSLv3_MAJOR;
00274     pv.minor = TLSv1_1_MINOR;
00275 
00276     return pv;
00277 }
00278 
00279 #endif
00280 
00281 
00282 ProtocolVersion MakeTLSv1_2(void)
00283 {
00284     ProtocolVersion pv;
00285     pv.major = SSLv3_MAJOR;
00286     pv.minor = TLSv1_2_MINOR;
00287 
00288     return pv;
00289 }
00290 
00291 
00292 static const byte master_label[MASTER_LABEL_SZ + 1] = "master secret";
00293 static const byte key_label   [KEY_LABEL_SZ + 1]    = "key expansion";
00294 
00295 
00296 int DeriveTlsKeys(CYASSL* ssl)
00297 {
00298     int length = 2 * ssl->specs.hash_size + 
00299                  2 * ssl->specs.key_size  +
00300                  2 * ssl->specs.iv_size;
00301     byte         seed[SEED_LEN];
00302     byte         key_data[MAX_PRF_DIG];
00303 
00304     XMEMCPY(seed, ssl->arrays->serverRandom, RAN_LEN);
00305     XMEMCPY(&seed[RAN_LEN], ssl->arrays->clientRandom, RAN_LEN);
00306 
00307     PRF(key_data, length, ssl->arrays->masterSecret, SECRET_LEN, key_label,
00308         KEY_LABEL_SZ, seed, SEED_LEN, IsAtLeastTLSv1_2(ssl),
00309         ssl->specs.mac_algorithm);
00310 
00311     return StoreKeys(ssl, key_data);
00312 }
00313 
00314 
00315 int MakeTlsMasterSecret(CYASSL* ssl)
00316 {
00317     byte seed[SEED_LEN];
00318     
00319     XMEMCPY(seed, ssl->arrays->clientRandom, RAN_LEN);
00320     XMEMCPY(&seed[RAN_LEN], ssl->arrays->serverRandom, RAN_LEN);
00321 
00322     PRF(ssl->arrays->masterSecret, SECRET_LEN,
00323         ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz,
00324         master_label, MASTER_LABEL_SZ, 
00325         seed, SEED_LEN, IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm);
00326 
00327 #ifdef SHOW_SECRETS
00328     {
00329         int i;
00330         printf("master secret: ");
00331         for (i = 0; i < SECRET_LEN; i++)
00332             printf("%02x", ssl->arrays->masterSecret[i]);
00333         printf("\n");
00334     }
00335 #endif
00336 
00337     return DeriveTlsKeys(ssl);
00338 }
00339 
00340 
00341 /* Used by EAP-TLS and EAP-TTLS to derive keying material from
00342  * the master_secret. */
00343 int CyaSSL_make_eap_keys(CYASSL* ssl, void* msk, unsigned int len,
00344                                                               const char* label)
00345 {
00346     byte seed[SEED_LEN];
00347 
00348     /*
00349      * As per RFC-5281, the order of the client and server randoms is reversed
00350      * from that used by the TLS protocol to derive keys.
00351      */
00352     XMEMCPY(seed, ssl->arrays->clientRandom, RAN_LEN);
00353     XMEMCPY(&seed[RAN_LEN], ssl->arrays->serverRandom, RAN_LEN);
00354 
00355     PRF((byte*)msk, len,
00356         ssl->arrays->masterSecret, SECRET_LEN,
00357         (const byte *)label, (word32)strlen(label),
00358         seed, SEED_LEN, IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm);
00359 
00360     return 0;
00361 }
00362 
00363 
00364 /*** next for static INLINE s copied from cyassl_int.c ***/
00365 
00366 /* convert 16 bit integer to opaque */
00367 static INLINE void c16toa(word16 u16, byte* c)
00368 {
00369     c[0] = (u16 >> 8) & 0xff;
00370     c[1] =  u16 & 0xff;
00371 }
00372 
00373 /* convert opaque to 16 bit integer */
00374 static INLINE void ato16(const byte* c, word16* u16)
00375 {
00376     *u16 = (c[0] << 8) | (c[1]);
00377 }
00378 
00379 
00380 /* convert 32 bit integer to opaque */
00381 static INLINE void c32toa(word32 u32, byte* c)
00382 {
00383     c[0] = (u32 >> 24) & 0xff;
00384     c[1] = (u32 >> 16) & 0xff;
00385     c[2] = (u32 >>  8) & 0xff;
00386     c[3] =  u32 & 0xff;
00387 }
00388 
00389 
00390 static INLINE word32 GetSEQIncrement(CYASSL* ssl, int verify)
00391 {
00392 #ifdef CYASSL_DTLS
00393     if (ssl->options.dtls) {
00394         if (verify)
00395             return ssl->keys.dtls_peer_sequence_number; /* explicit from peer */
00396         else
00397             return ssl->keys.dtls_sequence_number - 1; /* already incremented */
00398     }
00399 #endif
00400     if (verify)
00401         return ssl->keys.peer_sequence_number++; 
00402     else
00403         return ssl->keys.sequence_number++; 
00404 }
00405 
00406 
00407 #ifdef CYASSL_DTLS
00408 
00409 static INLINE word32 GetEpoch(CYASSL* ssl, int verify)
00410 {
00411     if (verify)
00412         return ssl->keys.dtls_peer_epoch; 
00413     else
00414         return ssl->keys.dtls_epoch; 
00415 }
00416 
00417 #endif /* CYASSL_DTLS */
00418 
00419 
00420 static INLINE const byte* GetMacSecret(CYASSL* ssl, int verify)
00421 {
00422     if ( (ssl->options.side == CLIENT_END && !verify) ||
00423          (ssl->options.side == SERVER_END &&  verify) )
00424         return ssl->keys.client_write_MAC_secret;
00425     else
00426         return ssl->keys.server_write_MAC_secret;
00427 }
00428 
00429 /*** end copy ***/
00430 
00431 
00432 /* TLS type HMAC */
00433 void TLS_hmac(CYASSL* ssl, byte* digest, const byte* in, word32 sz,
00434               int content, int verify)
00435 {
00436     Hmac hmac;
00437     byte seq[SEQ_SZ];
00438     byte length[LENGTH_SZ];
00439     byte inner[ENUM_LEN + VERSION_SZ + LENGTH_SZ]; /* type + version +len */
00440     int  type;
00441 
00442     XMEMSET(seq, 0, SEQ_SZ);
00443     c16toa((word16)sz, length);
00444 #ifdef CYASSL_DTLS
00445     if (ssl->options.dtls)
00446         c16toa((word16)GetEpoch(ssl, verify), seq);
00447 #endif
00448     c32toa(GetSEQIncrement(ssl, verify), &seq[sizeof(word32)]);
00449     
00450     switch (ssl->specs.mac_algorithm) {
00451         #ifndef NO_MD5
00452         case md5_mac:
00453         {
00454             type = MD5;
00455         }
00456         break;
00457         #endif
00458         #ifndef NO_SHA256
00459         case sha256_mac:
00460         {
00461             type = SHA256;
00462         }
00463         break;
00464         #endif
00465         #ifdef CYASSL_SHA384
00466         case sha384_mac:
00467         {
00468             type = SHA384;
00469         }
00470         break;
00471         #endif
00472 #ifndef NO_SHA
00473         case sha_mac:
00474         default:
00475         {
00476             type = SHA;
00477         }
00478         break;
00479 #endif
00480     }
00481     HmacSetKey(&hmac, type, GetMacSecret(ssl, verify), ssl->specs.hash_size);
00482     
00483     HmacUpdate(&hmac, seq, SEQ_SZ);                               /* seq_num */
00484     inner[0] = (byte)content;                                     /* type */
00485     inner[ENUM_LEN] = ssl->version.major;
00486     inner[ENUM_LEN + ENUM_LEN] = ssl->version.minor;              /* version */
00487     XMEMCPY(&inner[ENUM_LEN + VERSION_SZ], length, LENGTH_SZ);     /* length */
00488     HmacUpdate(&hmac, inner, sizeof(inner));
00489     HmacUpdate(&hmac, in, sz);                                /* content */
00490     HmacFinal(&hmac, digest);
00491 }
00492 
00493 #ifdef HAVE_TLS_EXTENSIONS
00494 
00495 static int TLSX_Append(TLSX** list, TLSX_Type type)
00496 {
00497     TLSX* extension;
00498 
00499     if (list == NULL) /* won't check type since this function is static */
00500         return BAD_FUNC_ARG;
00501 
00502     if ((extension = XMALLOC(sizeof(TLSX), 0, DYNAMIC_TYPE_TLSX)) == NULL)
00503         return MEMORY_E;
00504 
00505     extension->type = type;
00506     extension->data = NULL;
00507     extension->resp = 0;
00508     extension->next = *list;
00509     *list = extension;
00510 
00511     return 0;
00512 }
00513 
00514 #ifndef NO_CYASSL_SERVER
00515 
00516 static void TLSX_SetResponse(CYASSL* ssl, TLSX_Type type)
00517 {
00518     TLSX *ext = TLSX_Find(ssl->extensions, type);
00519 
00520     if (ext)
00521         ext->resp = 1;
00522 }
00523 
00524 #endif
00525 
00526 /* SNI - Server Name Indication */
00527 
00528 #ifdef HAVE_SNI
00529 
00530 static void TLSX_SNI_Free(SNI* sni)
00531 {
00532     if (sni) {
00533         switch (sni->type) {
00534             case CYASSL_SNI_HOST_NAME:
00535                 XFREE(sni->data.host_name, 0, DYNAMIC_TYPE_TLSX);
00536             break;
00537         }
00538 
00539         XFREE(sni, 0, DYNAMIC_TYPE_TLSX);
00540     }
00541 }
00542 
00543 static void TLSX_SNI_FreeAll(SNI* list)
00544 {
00545     SNI* sni;
00546 
00547     while ((sni = list)) {
00548         list = sni->next;
00549         TLSX_SNI_Free(sni);
00550     }
00551 }
00552 
00553 static int TLSX_SNI_Append(SNI** list, byte type, const void* data, word16 size)
00554 {
00555     SNI* sni;
00556 
00557     if (list == NULL)
00558         return BAD_FUNC_ARG;
00559 
00560     if ((sni = XMALLOC(sizeof(SNI), 0, DYNAMIC_TYPE_TLSX)) == NULL)
00561         return MEMORY_E;
00562 
00563     switch (type) {
00564         case CYASSL_SNI_HOST_NAME: {
00565             sni->data.host_name = XMALLOC(size + 1, 0, DYNAMIC_TYPE_TLSX);
00566 
00567             if (sni->data.host_name) {
00568                 XSTRNCPY(sni->data.host_name, (const char*) data, size);
00569                 sni->data.host_name[size] = 0;
00570             } else {
00571                 XFREE(sni, 0, DYNAMIC_TYPE_TLSX);
00572                 return MEMORY_E;
00573             }
00574         }
00575         break;
00576 
00577         default: /* invalid type */
00578             XFREE(sni, 0, DYNAMIC_TYPE_TLSX);
00579             return BAD_FUNC_ARG;
00580         break;
00581     }
00582 
00583     sni->type = type;
00584     sni->next = *list;
00585 
00586 #ifndef NO_CYASSL_SERVER
00587     sni->options = 0;
00588     sni->matched = 0;
00589 #endif
00590 
00591     *list = sni;
00592 
00593     return 0;
00594 }
00595 
00596 static word16 TLSX_SNI_GetSize(SNI* list)
00597 {
00598     SNI* sni;
00599     word16 length = OPAQUE16_LEN; /* list length */
00600 
00601     while ((sni = list)) {
00602         list = sni->next;
00603 
00604         length += ENUM_LEN + OPAQUE16_LEN; /* sni type + sni length */
00605 
00606         switch (sni->type) {
00607             case CYASSL_SNI_HOST_NAME:
00608                 length += XSTRLEN((char*) sni->data.host_name);
00609             break;
00610         }
00611     }
00612 
00613     return length;
00614 }
00615 
00616 static word16 TLSX_SNI_Write(SNI* list, byte* output)
00617 {
00618     SNI* sni;
00619     word16 length = 0;
00620     word16 offset = OPAQUE16_LEN; /* list length offset */
00621 
00622     while ((sni = list)) {
00623         list = sni->next;
00624 
00625         output[offset++] = sni->type; /* sni type */
00626 
00627         switch (sni->type) {
00628             case CYASSL_SNI_HOST_NAME:
00629                 length = XSTRLEN((char*) sni->data.host_name);
00630 
00631                 c16toa(length, output + offset); /* sni length */
00632                 offset += OPAQUE16_LEN;
00633 
00634                 XMEMCPY(output + offset, sni->data.host_name, length);
00635 
00636                 offset += length;
00637             break;
00638         }
00639     }
00640 
00641     c16toa(offset - OPAQUE16_LEN, output); /* writing list length */
00642 
00643     return offset;
00644 }
00645 
00646 static SNI* TLSX_SNI_Find(SNI *list, byte type)
00647 {
00648     SNI *sni = list;
00649 
00650     while (sni && sni->type != type)
00651         sni = sni->next;
00652 
00653     return sni;
00654 }
00655 
00656 #ifndef NO_CYASSL_SERVER
00657 static void TLSX_SNI_SetMatched(TLSX* extensions, byte type)
00658 {
00659     TLSX* extension = TLSX_Find(extensions, SERVER_NAME_INDICATION);
00660     SNI* sni = TLSX_SNI_Find(extension ? extension->data : NULL, type);
00661 
00662     if (sni) {
00663         sni->matched = 1;
00664         CYASSL_MSG("SNI did match!");
00665     }
00666 }
00667 
00668 byte TLSX_SNI_Matched(TLSX* extensions, byte type)
00669 {
00670     TLSX* extension = TLSX_Find(extensions, SERVER_NAME_INDICATION);
00671     SNI* sni = TLSX_SNI_Find(extension ? extension->data : NULL, type);
00672 
00673     if (sni)
00674         return sni->matched;
00675 
00676     return 0;
00677 }
00678 #endif
00679 
00680 static int TLSX_SNI_Parse(CYASSL* ssl, byte* input, word16 length,
00681                                                                  byte isRequest)
00682 {
00683 #ifndef NO_CYASSL_SERVER
00684     word16 size = 0;
00685     word16 offset = 0;
00686 #endif
00687 
00688     TLSX *extension = TLSX_Find(ssl->extensions, SERVER_NAME_INDICATION);
00689 
00690     if (!extension)
00691         extension = TLSX_Find(ssl->ctx->extensions, SERVER_NAME_INDICATION);
00692 
00693     if (!extension || !extension->data) {
00694         if (!isRequest) {
00695             CYASSL_MSG("Unexpected SNI response from server");
00696         }
00697 
00698         return 0; /* not using SNI */
00699     }
00700 
00701     if (!isRequest) {
00702         if (length) {
00703             CYASSL_MSG("SNI response should be empty!");
00704         }
00705 
00706         return 0; /* nothing to do */
00707     }
00708 
00709 #ifndef NO_CYASSL_SERVER
00710 
00711     if (OPAQUE16_LEN > length)
00712         return INCOMPLETE_DATA;
00713 
00714     ato16(input, &size);
00715     offset += OPAQUE16_LEN;
00716 
00717     /* validating sni list length */
00718     if (length != OPAQUE16_LEN + size)
00719         return INCOMPLETE_DATA;
00720 
00721     for (size = 0; offset < length; offset += size) {
00722         SNI *sni;
00723         byte type = input[offset++];
00724 
00725         if (offset + OPAQUE16_LEN > length)
00726             return INCOMPLETE_DATA;
00727 
00728         ato16(input + offset, &size);
00729         offset += OPAQUE16_LEN;
00730 
00731         if (offset + size > length)
00732             return INCOMPLETE_DATA;
00733 
00734         if (!(sni = TLSX_SNI_Find((SNI *) extension->data, type))) {
00735             continue; /* not using this SNI type */
00736         }
00737 
00738         switch(type) {
00739             case CYASSL_SNI_HOST_NAME: {
00740                 byte matched = (XSTRLEN(sni->data.host_name) == size)
00741                             && (XSTRNCMP(sni->data.host_name,
00742                                      (const char *) input + offset, size) == 0);
00743 
00744                 if (matched || sni->options & CYASSL_SNI_ANSWER_ON_MISMATCH) {
00745                     int r = TLSX_UseSNI(&ssl->extensions, type, (byte *) "", 0);
00746 
00747                     if (r) return r; /* throw error */
00748 
00749                     if (matched) TLSX_SNI_SetMatched(ssl->extensions, type);
00750                 } else if (!(sni->options & CYASSL_SNI_CONTINUE_ON_MISMATCH)) {
00751                     SendAlert(ssl, alert_fatal, unrecognized_name);
00752 
00753                     return UNKNOWN_SNI_HOST_NAME_E;
00754                 }
00755                 break;
00756             }
00757         }
00758 
00759         TLSX_SetResponse(ssl, SERVER_NAME_INDICATION);
00760     }
00761 
00762 #endif
00763 
00764     return 0;
00765 }
00766 
00767 int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, word16 size)
00768 {
00769     TLSX* extension = NULL;
00770     SNI*  sni       = NULL;
00771     int   ret       = 0;
00772 
00773     if (extensions == NULL || data == NULL)
00774         return BAD_FUNC_ARG;
00775 
00776     if ((ret = TLSX_SNI_Append(&sni, type, data, size)) != 0)
00777         return ret;
00778 
00779     extension = *extensions;
00780 
00781     /* find SNI extension if it already exists. */
00782     while (extension && extension->type != SERVER_NAME_INDICATION)
00783         extension = extension->next;
00784 
00785     /* push new SNI extension if it doesn't exists. */
00786     if (!extension) {
00787         if ((ret = TLSX_Append(extensions, SERVER_NAME_INDICATION)) != 0) {
00788             TLSX_SNI_Free(sni);
00789             return ret;
00790         }
00791 
00792         extension = *extensions;
00793     }
00794 
00795     /* push new SNI object to extension data. */
00796     sni->next = (SNI*) extension->data;
00797     extension->data = (void*) sni;
00798 
00799     /* look for another server name of the same type to remove (replacement) */
00800     while ((sni = sni->next)) {
00801         if (sni->next && sni->next->type == type) {
00802             SNI *next = sni->next;
00803 
00804             sni->next = next->next;
00805             TLSX_SNI_Free(next);
00806 
00807             break;
00808         }
00809     }
00810 
00811     return 0;
00812 }
00813 
00814 #ifndef NO_CYASSL_SERVER
00815 void TLSX_SNI_SetOptions(TLSX* extensions, byte type, byte options)
00816 {
00817     TLSX* extension = TLSX_Find(extensions, SERVER_NAME_INDICATION);
00818     SNI* sni = TLSX_SNI_Find(extension ? extension->data : NULL, type);
00819 
00820     if (sni)
00821         sni->options = options;
00822 }
00823 #endif
00824 
00825 #define SNI_FREE_ALL TLSX_SNI_FreeAll
00826 #define SNI_GET_SIZE TLSX_SNI_GetSize
00827 #define SNI_WRITE    TLSX_SNI_Write
00828 #define SNI_PARSE    TLSX_SNI_Parse
00829 
00830 #else
00831 
00832 #define SNI_FREE_ALL(x)
00833 #define SNI_GET_SIZE(x) 0
00834 #define SNI_WRITE(x) 0
00835 #define SNI_PARSE(x) 0
00836 
00837 #endif /* HAVE_SNI */
00838 
00839 TLSX* TLSX_Find(TLSX* list, TLSX_Type type)
00840 {
00841     TLSX* extension = list;
00842 
00843     while (extension && extension->type != type)
00844         extension = extension->next;
00845 
00846     return extension;
00847 }
00848 
00849 void TLSX_FreeAll(TLSX* list)
00850 {
00851     TLSX* extension;
00852 
00853     while ((extension = list)) {
00854         list = extension->next;
00855 
00856         switch (extension->type) {
00857             case SERVER_NAME_INDICATION:
00858                 SNI_FREE_ALL((SNI *) extension->data);
00859                 break;
00860         }
00861 
00862         XFREE(extension, 0, DYNAMIC_TYPE_TLSX);
00863     }
00864 }
00865 
00866 #define IS_OFF(semaphore, light) \
00867     ((semaphore)[(light) / 8] ^  (byte) (0x01 << ((light) % 8)))
00868 
00869 #define TURN_ON(semaphore, light) \
00870     ((semaphore)[(light) / 8] |= (byte) (0x01 << ((light) % 8)))
00871 
00872 static word16 TLSX_GetSize(TLSX* list, byte* semaphore, byte isRequest)
00873 {
00874     TLSX* extension;
00875     word16 length = 0;
00876 
00877     while ((extension = list)) {
00878         list = extension->next;
00879 
00880         if (!isRequest && !extension->resp)
00881             continue; /* skip! */
00882 
00883         if (IS_OFF(semaphore, extension->type)) {
00884             /* type + data length */
00885             length += HELLO_EXT_TYPE_SZ + OPAQUE16_LEN;
00886 
00887             switch (extension->type) {
00888                 case SERVER_NAME_INDICATION:
00889                     if (isRequest)
00890                         length += SNI_GET_SIZE((SNI *) extension->data);
00891                     break;
00892             }
00893 
00894             TURN_ON(semaphore, extension->type);
00895         }
00896     }
00897 
00898     return length;
00899 }
00900 
00901 static word16 TLSX_Write(TLSX* list, byte* output, byte* semaphore,
00902                                                                  byte isRequest)
00903 {
00904     TLSX* extension;
00905     word16 offset = 0;
00906     word16 length_offset = 0;
00907 
00908     while ((extension = list)) {
00909         list = extension->next;
00910 
00911         if (!isRequest && !extension->resp)
00912             continue; /* skip! */
00913 
00914         if (IS_OFF(semaphore, extension->type)) {
00915             /* extension type */
00916             c16toa(extension->type, output + offset);
00917             offset += HELLO_EXT_TYPE_SZ + OPAQUE16_LEN;
00918             length_offset = offset;
00919 
00920             /* extension data should be written internally */
00921             switch (extension->type) {
00922                 case SERVER_NAME_INDICATION:
00923                     if (isRequest)
00924                         offset += SNI_WRITE((SNI *) extension->data,
00925                                                                output + offset);
00926                     break;
00927             }
00928 
00929             /* writing extension data length */
00930             c16toa(offset - length_offset,
00931                                          output + length_offset - OPAQUE16_LEN);
00932 
00933             TURN_ON(semaphore, extension->type);
00934         }
00935     }
00936 
00937     return offset;
00938 }
00939 
00940 #ifndef NO_CYASSL_CLIENT
00941 
00942 word16 TLSX_GetRequestSize(CYASSL* ssl)
00943 {
00944     word16 length = 0;
00945 
00946     if (ssl && IsTLS(ssl)) {
00947         byte semaphore[16] = {0};
00948 
00949         if (ssl->extensions)
00950             length += TLSX_GetSize(ssl->extensions, semaphore, 1);
00951 
00952         if (ssl->ctx && ssl->ctx->extensions)
00953             length += TLSX_GetSize(ssl->ctx->extensions, semaphore, 1);
00954 
00955         if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz)
00956             length += ssl->suites->hashSigAlgoSz + HELLO_EXT_LEN;
00957     }
00958 
00959     if (length)
00960         length += OPAQUE16_LEN; /* for total length storage */
00961 
00962     return length;
00963 }
00964 
00965 word16 TLSX_WriteRequest(CYASSL* ssl, byte* output)
00966 {
00967     word16 offset = 0;
00968 
00969     if (ssl && IsTLS(ssl) && output) {
00970         byte semaphore[16] = {0};
00971 
00972         offset += OPAQUE16_LEN; /* extensions length */
00973 
00974         if (ssl->extensions)
00975             offset += TLSX_Write(ssl->extensions, output + offset,
00976                                                                   semaphore, 1);
00977 
00978         if (ssl->ctx && ssl->ctx->extensions)
00979             offset += TLSX_Write(ssl->ctx->extensions, output + offset,
00980                                                                   semaphore, 1);
00981 
00982         if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz)
00983         {
00984             int i;
00985             /* extension type */
00986             c16toa(HELLO_EXT_SIG_ALGO, output + offset);
00987             offset += HELLO_EXT_TYPE_SZ;
00988 
00989             /* extension data length */
00990             c16toa(OPAQUE16_LEN + ssl->suites->hashSigAlgoSz, output + offset);
00991             offset += OPAQUE16_LEN;
00992 
00993             /* sig algos length */
00994             c16toa(ssl->suites->hashSigAlgoSz, output + offset);
00995             offset += OPAQUE16_LEN;
00996 
00997             /* sig algos */
00998             for (i = 0; i < ssl->suites->hashSigAlgoSz; i++, offset++)
00999                 output[offset] = ssl->suites->hashSigAlgo[i];
01000         }
01001 
01002         if (offset > OPAQUE16_LEN)
01003             c16toa(offset - OPAQUE16_LEN, output); /* extensions length */
01004     }
01005 
01006     return offset;
01007 }
01008 
01009 #endif /* NO_CYASSL_CLIENT */
01010 
01011 #ifndef NO_CYASSL_SERVER
01012 
01013 word16 TLSX_GetResponseSize(CYASSL* ssl)
01014 {
01015     word16 length = 0;
01016     byte semaphore[16] = {0};
01017 
01018     if (ssl && IsTLS(ssl))
01019         length += TLSX_GetSize(ssl->extensions, semaphore, 0);
01020 
01021     /* All the response data is set at the ssl object only, so no ctx here. */
01022 
01023     if (length)
01024         length += OPAQUE16_LEN; /* for total length storage */
01025 
01026     return length;
01027 }
01028 
01029 word16 TLSX_WriteResponse(CYASSL *ssl, byte* output)
01030 {
01031     word16 offset = 0;
01032 
01033     if (ssl && IsTLS(ssl) && output) {
01034         byte semaphore[16] = {0};
01035 
01036         offset += OPAQUE16_LEN; /* extensions length */
01037 
01038         offset += TLSX_Write(ssl->extensions, output + offset, semaphore, 0);
01039 
01040         if (offset > OPAQUE16_LEN)
01041             c16toa(offset - OPAQUE16_LEN, output); /* extensions length */
01042     }
01043 
01044     return offset;
01045 }
01046 
01047 #endif /* NO_CYASSL_SERVER */
01048 
01049 int TLSX_Parse(CYASSL* ssl, byte* input, word16 length, byte isRequest,
01050                                                                  Suites *suites)
01051 {
01052     int ret = 0;
01053     word16 offset = 0;
01054 
01055     if (!ssl || !input || !suites)
01056         return BAD_FUNC_ARG;
01057 
01058     while (ret == 0 && offset < length) {
01059         word16 type;
01060         word16 size;
01061 
01062         if (length - offset < HELLO_EXT_TYPE_SZ + OPAQUE16_LEN)
01063             return INCOMPLETE_DATA;
01064 
01065         ato16(input + offset, &type);
01066         offset += HELLO_EXT_TYPE_SZ;
01067 
01068         ato16(input + offset, &size);
01069         offset += OPAQUE16_LEN;
01070 
01071         if (offset + size > length)
01072             return INCOMPLETE_DATA;
01073 
01074         switch (type) {
01075             case SERVER_NAME_INDICATION:
01076                 CYASSL_MSG("SNI extension received");
01077 
01078                 ret = SNI_PARSE(ssl, input + offset, size, isRequest);
01079                 break;
01080 
01081             case HELLO_EXT_SIG_ALGO:
01082                 if (isRequest) {
01083                     /* do not mess with offset inside the switch! */
01084                     if (IsAtLeastTLSv1_2(ssl)) {
01085                         ato16(input + offset, &suites->hashSigAlgoSz);
01086 
01087                         if (suites->hashSigAlgoSz > size - OPAQUE16_LEN)
01088                             return INCOMPLETE_DATA;
01089 
01090                         XMEMCPY(suites->hashSigAlgo,
01091                                 input + offset + OPAQUE16_LEN,
01092                                 min(suites->hashSigAlgoSz,
01093                                                         HELLO_EXT_SIGALGO_MAX));
01094                     }
01095                 } else {
01096                     CYASSL_MSG("Servers MUST NOT send SIG ALGO extension.");
01097                 }
01098 
01099                 break;
01100         }
01101 
01102         /* offset should be updated here! */
01103         offset += size;
01104     }
01105 
01106     return ret;
01107 }
01108 
01109 /* undefining semaphore macros */
01110 #undef IS_OFF
01111 #undef TURN_ON
01112 
01113 #endif /* HAVE_TLS_EXTENSIONS */
01114 
01115 
01116 #ifndef NO_CYASSL_CLIENT
01117 
01118 #ifndef NO_OLD_TLS
01119 
01120     CYASSL_METHOD* CyaTLSv1_client_method(void)
01121     {
01122         CYASSL_METHOD* method =
01123                              (CYASSL_METHOD*) XMALLOC(sizeof(CYASSL_METHOD), 0,
01124                                                       DYNAMIC_TYPE_METHOD);
01125         if (method)
01126             InitSSL_Method(method, MakeTLSv1());
01127         return method;
01128     }
01129 
01130 
01131     CYASSL_METHOD* CyaTLSv1_1_client_method(void)
01132     {
01133         CYASSL_METHOD* method =
01134                               (CYASSL_METHOD*) XMALLOC(sizeof(CYASSL_METHOD), 0,
01135                                                        DYNAMIC_TYPE_METHOD);
01136         if (method)
01137             InitSSL_Method(method, MakeTLSv1_1());
01138         return method;
01139     }
01140 
01141 #endif /* !NO_OLD_TLS */
01142 
01143 #ifndef NO_SHA256   /* can't use without SHA256 */
01144 
01145     CYASSL_METHOD* CyaTLSv1_2_client_method(void)
01146     {
01147         CYASSL_METHOD* method =
01148                               (CYASSL_METHOD*) XMALLOC(sizeof(CYASSL_METHOD), 0,
01149                                                        DYNAMIC_TYPE_METHOD);
01150         if (method)
01151             InitSSL_Method(method, MakeTLSv1_2());
01152         return method;
01153     }
01154 
01155 #endif
01156 
01157 
01158     CYASSL_METHOD* CyaSSLv23_client_method(void)
01159     {
01160         CYASSL_METHOD* method =
01161                               (CYASSL_METHOD*) XMALLOC(sizeof(CYASSL_METHOD), 0,
01162                                                        DYNAMIC_TYPE_METHOD);
01163         if (method) {
01164 #ifndef NO_SHA256         /* 1.2 requires SHA256 */
01165             InitSSL_Method(method, MakeTLSv1_2());
01166 #else
01167             InitSSL_Method(method, MakeTLSv1_1());
01168 #endif
01169 #ifndef NO_OLD_TLS
01170             method->downgrade = 1;
01171 #endif 
01172         }
01173         return method;
01174     }
01175 
01176 
01177 #endif /* NO_CYASSL_CLIENT */
01178 
01179 
01180 
01181 #ifndef NO_CYASSL_SERVER
01182 
01183 #ifndef NO_OLD_TLS
01184 
01185     CYASSL_METHOD* CyaTLSv1_server_method(void)
01186     {
01187         CYASSL_METHOD* method =
01188                               (CYASSL_METHOD*) XMALLOC(sizeof(CYASSL_METHOD), 0,
01189                                                        DYNAMIC_TYPE_METHOD);
01190         if (method) {
01191             InitSSL_Method(method, MakeTLSv1());
01192             method->side = SERVER_END;
01193         }
01194         return method;
01195     }
01196 
01197 
01198     CYASSL_METHOD* CyaTLSv1_1_server_method(void)
01199     {
01200         CYASSL_METHOD* method =
01201                               (CYASSL_METHOD*) XMALLOC(sizeof(CYASSL_METHOD), 0,
01202                                                        DYNAMIC_TYPE_METHOD);
01203         if (method) {
01204             InitSSL_Method(method, MakeTLSv1_1());
01205             method->side = SERVER_END;
01206         }
01207         return method;
01208     }
01209 
01210 #endif /* !NO_OLD_TLS */
01211 
01212 #ifndef NO_SHA256   /* can't use without SHA256 */
01213 
01214     CYASSL_METHOD* CyaTLSv1_2_server_method(void)
01215     {
01216         CYASSL_METHOD* method =
01217                               (CYASSL_METHOD*) XMALLOC(sizeof(CYASSL_METHOD), 0,
01218                                                        DYNAMIC_TYPE_METHOD);
01219         if (method) {
01220             InitSSL_Method(method, MakeTLSv1_2());
01221             method->side = SERVER_END;
01222         }
01223         return method;
01224     }
01225 
01226 #endif
01227 
01228 
01229     CYASSL_METHOD* CyaSSLv23_server_method(void)
01230     {
01231         CYASSL_METHOD* method =
01232                               (CYASSL_METHOD*) XMALLOC(sizeof(CYASSL_METHOD), 0,
01233                                                        DYNAMIC_TYPE_METHOD);
01234         if (method) {
01235 #ifndef NO_SHA256         /* 1.2 requires SHA256 */
01236             InitSSL_Method(method, MakeTLSv1_2());
01237 #else
01238             InitSSL_Method(method, MakeTLSv1_1());
01239 #endif
01240             method->side      = SERVER_END;
01241 #ifndef NO_OLD_TLS
01242             method->downgrade = 1;
01243 #endif /* !NO_OLD_TLS */
01244         }
01245         return method;
01246     }
01247 
01248 
01249 
01250 #endif /* NO_CYASSL_SERVER */
01251 #endif /* NO_TLS */
01252