CyaSSL is an SSL library for devices like mbed.
Fork of CyaSSL by
Embed:
(wiki syntax)
Show/hide line numbers
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 Wed Jul 13 2022 00:57:02 by 1.7.2