CyaSSL is an SSL library for devices like mbed.

Dependents:   cyassl-client Sync

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-2009 Sawtooth Consulting Ltd.
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 
00023 #include "ssl.h"
00024 #include "cyassl_int.h"
00025 #include "cyassl_error.h"
00026 #include "ctc_hmac.h"
00027 
00028 
00029 
00030 #ifndef NO_TLS
00031 
00032 
00033 #ifndef min
00034 
00035     static INLINE word32 min(word32 a, word32 b)
00036     {
00037         return a > b ? b : a;
00038     }
00039 
00040 #endif /* min */
00041 
00042 
00043 /* calculate XOR for TLSv1 PRF */
00044 static INLINE void get_xor(byte *digest, word32 digLen, byte* md5, byte* sha)
00045 {
00046     word32 i;
00047 
00048     for (i = 0; i < digLen; i++) 
00049         digest[i] = md5[i] ^ sha[i];
00050 }
00051 
00052 
00053 
00054 /* compute p_hash for MD5, SHA-1, or SHA-256 for TLSv1 PRF */
00055 void p_hash(byte* result, word32 resLen, const byte* secret, word32 secLen,
00056             const byte* seed, word32 seedLen, int hash)
00057 {
00058     word32   len = hash == md5_mac ? MD5_DIGEST_SIZE : hash == sha_mac ?
00059                                            SHA_DIGEST_SIZE : SHA256_DIGEST_SIZE;
00060     word32   times = resLen / len;
00061     word32   lastLen = resLen % len;
00062     word32   lastTime;
00063     word32   i;
00064     word32   idx = 0;
00065     byte     previous[SHA256_DIGEST_SIZE];  /* max size */
00066     byte     current[SHA256_DIGEST_SIZE];   /* max size */
00067 
00068     Hmac hmac;
00069 
00070     if (lastLen) times += 1;
00071     lastTime = times - 1;
00072 
00073     HmacSetKey(&hmac, hash == md5_mac ? MD5 : hash == sha_mac ? SHA : SHA256,
00074                secret, secLen);
00075     HmacUpdate(&hmac, seed, seedLen);       /* A0 = seed */
00076     HmacFinal(&hmac, previous);             /* A1 */
00077 
00078     for (i = 0; i < times; i++) {
00079         HmacUpdate(&hmac, previous, len);
00080         HmacUpdate(&hmac, seed, seedLen);
00081         HmacFinal(&hmac, current);
00082 
00083         if ( (i == lastTime) && lastLen)
00084             XMEMCPY(&result[idx], current, lastLen);
00085         else {
00086             XMEMCPY(&result[idx], current, len);
00087             idx += len;
00088             HmacUpdate(&hmac, previous, len);
00089             HmacFinal(&hmac, previous);
00090         }
00091     }
00092 }
00093 
00094 
00095 
00096 /* compute TLSv1 PRF (pseudo random function using HMAC) */
00097 static void PRF(byte* digest, word32 digLen, const byte* secret, word32 secLen,
00098             const byte* label, word32 labLen, const byte* seed, word32 seedLen,
00099             int useSha256)
00100 {
00101     word32 half = (secLen + 1) / 2;
00102 
00103     byte md5_half[MAX_PRF_HALF];        /* half is real size */
00104     byte sha_half[MAX_PRF_HALF];        /* half is real size */
00105     byte labelSeed[MAX_PRF_LABSEED];    /* labLen + seedLen is real size */
00106     byte md5_result[MAX_PRF_DIG];       /* digLen is real size */
00107     byte sha_result[MAX_PRF_DIG];       /* digLen is real size */
00108 
00109     if (half > MAX_PRF_HALF)
00110         return;
00111     if (labLen + seedLen > MAX_PRF_LABSEED)
00112         return;
00113     if (digLen > MAX_PRF_DIG)
00114         return;
00115     
00116     XMEMCPY(md5_half, secret, half);
00117     XMEMCPY(sha_half, secret + half - secLen % 2, half);
00118 
00119     XMEMCPY(labelSeed, label, labLen);
00120     XMEMCPY(labelSeed + labLen, seed, seedLen);
00121 
00122     if (useSha256) {
00123         p_hash(digest, digLen, secret, secLen, labelSeed, labLen + seedLen,
00124                sha256_mac);
00125         return;
00126     }
00127 
00128     p_hash(md5_result, digLen, md5_half, half, labelSeed, labLen + seedLen,
00129            md5_mac);
00130     p_hash(sha_result, digLen, sha_half, half, labelSeed, labLen + seedLen,
00131            sha_mac);
00132     get_xor(digest, digLen, md5_result, sha_result);
00133 }
00134 
00135 
00136 void BuildTlsFinished(SSL* ssl, Hashes* hashes, const byte* sender)
00137 {
00138     const byte* side;
00139     byte handshake_hash[FINISHED_SZ];
00140 
00141     Md5Final(&ssl->hashMd5, handshake_hash);
00142     ShaFinal(&ssl->hashSha, &handshake_hash[MD5_DIGEST_SIZE]);
00143    
00144     if ( XSTRNCMP((const char*)sender, (const char*)client, SIZEOF_SENDER) == 0)
00145         side = tls_client;
00146     else
00147         side = tls_server;
00148 
00149     PRF(hashes->md5, TLS_FINISHED_SZ, ssl->arrays.masterSecret, SECRET_LEN,
00150         side, FINISHED_LABEL_SZ, handshake_hash, FINISHED_SZ,
00151         IsAtLeastTLSv1_2(ssl));
00152 }
00153 
00154 
00155 ProtocolVersion MakeTLSv1(void)
00156 {
00157     ProtocolVersion pv;
00158     pv.major = SSLv3_MAJOR;
00159     pv.minor = TLSv1_MINOR;
00160 
00161     return pv;
00162 }
00163 
00164 
00165 ProtocolVersion MakeTLSv1_1(void)
00166 {
00167     ProtocolVersion pv;
00168     pv.major = SSLv3_MAJOR;
00169     pv.minor = TLSv1_1_MINOR;
00170 
00171     return pv;
00172 }
00173 
00174 
00175 ProtocolVersion MakeTLSv1_2(void)
00176 {
00177     ProtocolVersion pv;
00178     pv.major = SSLv3_MAJOR;
00179     pv.minor = TLSv1_2_MINOR;
00180 
00181     return pv;
00182 }
00183 
00184 
00185 static const byte master_label[MASTER_LABEL_SZ + 1] = "master secret";
00186 static const byte key_label   [KEY_LABEL_SZ + 1]    = "key expansion";
00187 
00188 
00189 int DeriveTlsKeys(SSL* ssl)
00190 {
00191     int length = 2 * ssl->specs.hash_size + 
00192                  2 * ssl->specs.key_size  +
00193                  2 * ssl->specs.iv_size;
00194     byte         seed[SEED_LEN];
00195     byte         key_data[MAX_PRF_DIG];
00196 
00197     XMEMCPY(seed, ssl->arrays.serverRandom, RAN_LEN);
00198     XMEMCPY(&seed[RAN_LEN], ssl->arrays.clientRandom, RAN_LEN);
00199 
00200     PRF(key_data, length, ssl->arrays.masterSecret, SECRET_LEN, key_label,
00201         KEY_LABEL_SZ, seed, SEED_LEN, IsAtLeastTLSv1_2(ssl));
00202 
00203     return StoreKeys(ssl, key_data);
00204 }
00205 
00206 
00207 int MakeTlsMasterSecret(SSL* ssl)
00208 {
00209     byte seed[SEED_LEN];
00210     
00211     XMEMCPY(seed, ssl->arrays.clientRandom, RAN_LEN);
00212     XMEMCPY(&seed[RAN_LEN], ssl->arrays.serverRandom, RAN_LEN);
00213 
00214     PRF(ssl->arrays.masterSecret, SECRET_LEN,
00215         ssl->arrays.preMasterSecret, ssl->arrays.preMasterSz,
00216         master_label, MASTER_LABEL_SZ, 
00217         seed, SEED_LEN, IsAtLeastTLSv1_2(ssl));
00218 
00219 #ifdef SHOW_SECRETS
00220     {
00221         int i;
00222         printf("master secret: ");
00223         for (i = 0; i < SECRET_LEN; i++)
00224             printf("%02x", ssl->arrays.masterSecret[i]);
00225         printf("\n");
00226     }
00227 #endif
00228 
00229     return DeriveTlsKeys(ssl);
00230 }
00231 
00232 
00233 /*** next for static INLINE s copied from cyassl_int.c ***/
00234 
00235 /* convert 16 bit integer to opaque */
00236 static void INLINE c16toa(word16 u16, byte* c)
00237 {
00238     c[0] = (u16 >> 8) & 0xff;
00239     c[1] =  u16 & 0xff;
00240 }
00241 
00242 
00243 /* convert 32 bit integer to opaque */
00244 static INLINE void c32toa(word32 u32, byte* c)
00245 {
00246     c[0] = (u32 >> 24) & 0xff;
00247     c[1] = (u32 >> 16) & 0xff;
00248     c[2] = (u32 >>  8) & 0xff;
00249     c[3] =  u32 & 0xff;
00250 }
00251 
00252 
00253 static INLINE word32 GetSEQIncrement(SSL* ssl, int verify)
00254 {
00255 #ifdef CYASSL_DTLS
00256     if (ssl->options.dtls) {
00257         if (verify)
00258             return ssl->keys.dtls_peer_sequence_number; /* explicit from peer */
00259         else
00260             return ssl->keys.dtls_sequence_number - 1; /* already incremented */
00261     }
00262 #endif
00263     if (verify)
00264         return ssl->keys.peer_sequence_number++; 
00265     else
00266         return ssl->keys.sequence_number++; 
00267 }
00268 
00269 
00270 #ifdef CYASSL_DTLS
00271 
00272 static INLINE word32 GetEpoch(SSL* ssl, int verify)
00273 {
00274     if (verify)
00275         return ssl->keys.dtls_peer_epoch; 
00276     else
00277         return ssl->keys.dtls_epoch; 
00278 }
00279 
00280 #endif /* CYASSL_DTLS */
00281 
00282 
00283 static INLINE const byte* GetMacSecret(SSL* ssl, int verify)
00284 {
00285     if ( (ssl->options.side == CLIENT_END && !verify) ||
00286          (ssl->options.side == SERVER_END &&  verify) )
00287         return ssl->keys.client_write_MAC_secret;
00288     else
00289         return ssl->keys.server_write_MAC_secret;
00290 }
00291 
00292 /*** end copy ***/
00293 
00294 
00295 /* TLS type HAMC */
00296 void TLS_hmac(SSL* ssl, byte* digest, const byte* buffer, word32 sz,
00297               int content, int verify)
00298 {
00299     Hmac hmac;
00300     byte seq[SEQ_SZ] = { 0x00, 0x00, 0x00, 0x00 };
00301     byte length[LENGTH_SZ];
00302     byte inner[ENUM_LEN + VERSION_SZ + LENGTH_SZ]; /* type + version +len */
00303     int  type;
00304 
00305     c16toa((word16)sz, length);
00306 #ifdef CYASSL_DTLS
00307     if (ssl->options.dtls)
00308         c16toa(GetEpoch(ssl, verify), seq);
00309 #endif
00310     c32toa(GetSEQIncrement(ssl, verify), &seq[sizeof(word32)]);
00311     
00312     if (ssl->specs.mac_algorithm == md5_mac)
00313         type = MD5;
00314     else
00315         type = SHA;
00316     HmacSetKey(&hmac, type, GetMacSecret(ssl, verify), ssl->specs.hash_size);
00317     
00318     HmacUpdate(&hmac, seq, SEQ_SZ);                               /* seq_num */
00319     inner[0] = content;                                           /* type */
00320     inner[ENUM_LEN] = ssl->version.major;
00321     inner[ENUM_LEN + ENUM_LEN] = ssl->version.minor;              /* version */
00322     XMEMCPY(&inner[ENUM_LEN + VERSION_SZ], length, LENGTH_SZ);     /* length */
00323     HmacUpdate(&hmac, inner, sizeof(inner));
00324     HmacUpdate(&hmac, buffer, sz);                                /* content */
00325     HmacFinal(&hmac, digest);
00326 }
00327 
00328 
00329 #ifndef NO_CYASSL_CLIENT
00330 
00331     SSL_METHOD* TLSv1_client_method(void)
00332     {
00333         SSL_METHOD* method = (SSL_METHOD*) XMALLOC(sizeof(SSL_METHOD), 0,
00334                                                    DYNAMIC_TYPE_METHOD);
00335         if (method)
00336             InitSSL_Method(method, MakeTLSv1());
00337         return method;
00338     }
00339 
00340 
00341     SSL_METHOD* TLSv1_1_client_method(void)
00342     {
00343         SSL_METHOD* method = (SSL_METHOD*) XMALLOC(sizeof(SSL_METHOD), 0,
00344                                                    DYNAMIC_TYPE_METHOD);
00345         if (method)
00346             InitSSL_Method(method, MakeTLSv1_1());
00347         return method;
00348     }
00349 
00350 
00351     SSL_METHOD* TLSv1_2_client_method(void)
00352     {
00353         SSL_METHOD* method = (SSL_METHOD*) XMALLOC(sizeof(SSL_METHOD), 0,
00354                                                    DYNAMIC_TYPE_METHOD);
00355         if (method)
00356             InitSSL_Method(method, MakeTLSv1_2());
00357         return method;
00358     }
00359 
00360 
00361     /* TODO: add downgrade */
00362     SSL_METHOD* SSLv23_client_method(void)
00363     {
00364         SSL_METHOD* method = (SSL_METHOD*) XMALLOC(sizeof(SSL_METHOD), 0,
00365                                                    DYNAMIC_TYPE_METHOD);
00366         if (method)
00367             InitSSL_Method(method, MakeTLSv1());
00368         return method;
00369     }
00370 
00371 
00372 #endif /* NO_CYASSL_CLIENT */
00373 
00374 
00375 
00376 #ifndef NO_CYASSL_SERVER
00377 
00378     SSL_METHOD* TLSv1_server_method(void)
00379     {
00380         SSL_METHOD* method = (SSL_METHOD*) XMALLOC(sizeof(SSL_METHOD), 0, 
00381                                                    DYNAMIC_TYPE_METHOD);
00382         if (method) {
00383             InitSSL_Method(method, MakeTLSv1());
00384             method->side = SERVER_END;
00385         }
00386         return method;
00387     }
00388 
00389 
00390     SSL_METHOD* TLSv1_1_server_method(void)
00391     {
00392         SSL_METHOD* method = (SSL_METHOD*) XMALLOC(sizeof(SSL_METHOD), 0,
00393                                                    DYNAMIC_TYPE_METHOD);
00394         if (method) {
00395             InitSSL_Method(method, MakeTLSv1_1());
00396             method->side = SERVER_END;
00397         }
00398         return method;
00399     }
00400 
00401 
00402     SSL_METHOD* TLSv1_2_server_method(void)
00403     {
00404         SSL_METHOD* method = (SSL_METHOD*) XMALLOC(sizeof(SSL_METHOD), 0,
00405                                                    DYNAMIC_TYPE_METHOD);
00406         if (method) {
00407             InitSSL_Method(method, MakeTLSv1_2());
00408             method->side = SERVER_END;
00409         }
00410         return method;
00411     }
00412 
00413 
00414     SSL_METHOD *SSLv23_server_method(void)
00415     {
00416         SSL_METHOD* method = (SSL_METHOD*) XMALLOC(sizeof(SSL_METHOD), 0,
00417                                                    DYNAMIC_TYPE_METHOD);
00418         if (method) {
00419             InitSSL_Method(method, MakeTLSv1());
00420             method->side      = SERVER_END;
00421             method->downgrade = 1;
00422         }
00423         return method;
00424     }
00425 
00426 
00427 
00428 #endif /* NO_CYASSL_SERVER */
00429 
00430 #else /* NO_TLS */
00431 
00432 /* catch CyaSSL programming errors */
00433 void BuildTlsFinished(SSL* ssl, Hashes* hashes, const byte* sender)
00434 {
00435    
00436 }
00437 
00438 
00439 int DeriveTlsKeys(SSL* ssl)
00440 {
00441     return -1;
00442 }
00443 
00444 
00445 int MakeTlsMasterSecret(SSL* ssl)
00446 { 
00447     return -1;
00448 }
00449 
00450 #endif /* NO_TLS */
00451