Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of CyaSSL-forEncrypt by
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
Generated on Mon Jul 25 2022 10:27:45 by
1.7.2
