cyassl re-port with cellular comms, PSK test
Dependencies: VodafoneUSBModem_bleedingedge2 mbed-rtos mbed-src
tls.c
00001 /* tls.c 00002 * 00003 * Copyright (C) 2006-2012 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 #ifdef HAVE_CONFIG_H 00023 #include <config.h> 00024 #endif 00025 00026 #include <cyassl/ssl.h> 00027 #include <cyassl/internal.h> 00028 #include <cyassl/error.h> 00029 #include <cyassl/ctaocrypt/hmac.h> 00030 00031 00032 00033 #ifndef NO_TLS 00034 00035 00036 #ifndef min 00037 00038 static INLINE word32 min(word32 a, word32 b) 00039 { 00040 return a > b ? b : a; 00041 } 00042 00043 #endif /* min */ 00044 00045 00046 #ifdef CYASSL_SHA384 00047 #define PHASH_MAX_DIGEST_SIZE SHA384_DIGEST_SIZE 00048 #else 00049 #define PHASH_MAX_DIGEST_SIZE SHA256_DIGEST_SIZE 00050 #endif 00051 00052 /* compute p_hash for MD5, SHA-1, SHA-256, or SHA-384 for TLSv1 PRF */ 00053 static void p_hash(byte* result, word32 resLen, const byte* secret, 00054 word32 secLen, const byte* seed, word32 seedLen, int hash) 00055 { 00056 word32 len = SHA_DIGEST_SIZE; 00057 word32 times; 00058 word32 lastLen; 00059 word32 lastTime; 00060 word32 i; 00061 word32 idx = 0; 00062 byte previous[PHASH_MAX_DIGEST_SIZE]; /* max size */ 00063 byte current[PHASH_MAX_DIGEST_SIZE]; /* max size */ 00064 00065 Hmac hmac; 00066 00067 switch (hash) { 00068 #ifndef NO_MD5 00069 case md5_mac: 00070 { 00071 len = MD5_DIGEST_SIZE; 00072 hash = MD5; 00073 } 00074 break; 00075 #endif 00076 #ifndef NO_SHA256 00077 case sha256_mac: 00078 { 00079 len = SHA256_DIGEST_SIZE; 00080 hash = SHA256; 00081 } 00082 break; 00083 #endif 00084 #ifdef CYASSL_SHA384 00085 case sha384_mac: 00086 { 00087 len = SHA384_DIGEST_SIZE; 00088 hash = SHA384; 00089 } 00090 break; 00091 #endif 00092 case sha_mac: 00093 default: 00094 { 00095 len = SHA_DIGEST_SIZE; 00096 hash = SHA; 00097 } 00098 break; 00099 } 00100 00101 times = resLen / len; 00102 lastLen = resLen % len; 00103 if (lastLen) times += 1; 00104 lastTime = times - 1; 00105 00106 HmacSetKey(&hmac, hash, secret, secLen); 00107 HmacUpdate(&hmac, seed, seedLen); /* A0 = seed */ 00108 HmacFinal(&hmac, previous); /* A1 */ 00109 00110 for (i = 0; i < times; i++) { 00111 HmacUpdate(&hmac, previous, len); 00112 HmacUpdate(&hmac, seed, seedLen); 00113 HmacFinal(&hmac, current); 00114 00115 if ( (i == lastTime) && lastLen) 00116 XMEMCPY(&result[idx], current, min(lastLen, sizeof(current))); 00117 else { 00118 XMEMCPY(&result[idx], current, len); 00119 idx += len; 00120 HmacUpdate(&hmac, previous, len); 00121 HmacFinal(&hmac, previous); 00122 } 00123 } 00124 } 00125 00126 00127 00128 #ifndef NO_MD5 00129 00130 /* calculate XOR for TLSv1 PRF */ 00131 static INLINE void get_xor(byte *digest, word32 digLen, byte* md5, byte* sha) 00132 { 00133 word32 i; 00134 00135 for (i = 0; i < digLen; i++) 00136 digest[i] = md5[i] ^ sha[i]; 00137 } 00138 00139 00140 /* compute TLSv1 PRF (pseudo random function using HMAC) */ 00141 static void doPRF(byte* digest, word32 digLen, const byte* secret,word32 secLen, 00142 const byte* label, word32 labLen, const byte* seed, word32 seedLen) 00143 { 00144 word32 half = (secLen + 1) / 2; 00145 00146 byte md5_half[MAX_PRF_HALF]; /* half is real size */ 00147 byte sha_half[MAX_PRF_HALF]; /* half is real size */ 00148 byte labelSeed[MAX_PRF_LABSEED]; /* labLen + seedLen is real size */ 00149 byte md5_result[MAX_PRF_DIG]; /* digLen is real size */ 00150 byte sha_result[MAX_PRF_DIG]; /* digLen is real size */ 00151 00152 if (half > MAX_PRF_HALF) 00153 return; 00154 if (labLen + seedLen > MAX_PRF_LABSEED) 00155 return; 00156 if (digLen > MAX_PRF_DIG) 00157 return; 00158 00159 XMEMCPY(md5_half, secret, half); 00160 XMEMCPY(sha_half, secret + half - secLen % 2, half); 00161 00162 XMEMCPY(labelSeed, label, labLen); 00163 XMEMCPY(labelSeed + labLen, seed, seedLen); 00164 00165 p_hash(md5_result, digLen, md5_half, half, labelSeed, labLen + seedLen, 00166 md5_mac); 00167 p_hash(sha_result, digLen, sha_half, half, labelSeed, labLen + seedLen, 00168 sha_mac); 00169 get_xor(digest, digLen, md5_result, sha_result); 00170 } 00171 00172 #endif 00173 00174 00175 /* Wrapper to call straight thru to p_hash in TSL 1.2 cases to remove stack 00176 use */ 00177 static void PRF(byte* digest, word32 digLen, const byte* secret, word32 secLen, 00178 const byte* label, word32 labLen, const byte* seed, word32 seedLen, 00179 int useAtLeastSha256, int hash_type) 00180 { 00181 if (useAtLeastSha256) { 00182 byte labelSeed[MAX_PRF_LABSEED]; /* labLen + seedLen is real size */ 00183 00184 if (labLen + seedLen > MAX_PRF_LABSEED) 00185 return; 00186 00187 XMEMCPY(labelSeed, label, labLen); 00188 XMEMCPY(labelSeed + labLen, seed, seedLen); 00189 00190 /* If a cipher suite wants an algorithm better than sha256, it 00191 * should use better. */ 00192 if (hash_type < sha256_mac) 00193 hash_type = sha256_mac; 00194 p_hash(digest, digLen, secret, secLen, labelSeed, labLen + seedLen, 00195 hash_type); 00196 } 00197 #ifndef NO_MD5 00198 else 00199 doPRF(digest, digLen, secret, secLen, label, labLen, seed, seedLen); 00200 #endif 00201 } 00202 00203 00204 #ifdef CYASSL_SHA384 00205 #define HSHASH_SZ SHA384_DIGEST_SIZE 00206 #else 00207 #define HSHASH_SZ FINISHED_SZ 00208 #endif 00209 00210 00211 void BuildTlsFinished(CYASSL* ssl, Hashes* hashes, const byte* sender) 00212 { 00213 const byte* side; 00214 byte handshake_hash[HSHASH_SZ]; 00215 word32 hashSz = FINISHED_SZ; 00216 00217 #ifndef NO_MD5 00218 Md5Final(&ssl->hashMd5, handshake_hash); 00219 ShaFinal(&ssl->hashSha, &handshake_hash[MD5_DIGEST_SIZE]); 00220 #endif 00221 00222 if (IsAtLeastTLSv1_2(ssl)) { 00223 #ifndef NO_SHA256 00224 if (ssl->specs.mac_algorithm <= sha256_mac) { 00225 Sha256Final(&ssl->hashSha256, handshake_hash); 00226 hashSz = SHA256_DIGEST_SIZE; 00227 } 00228 #endif 00229 #ifdef CYASSL_SHA384 00230 if (ssl->specs.mac_algorithm == sha384_mac) { 00231 Sha384Final(&ssl->hashSha384, handshake_hash); 00232 hashSz = SHA384_DIGEST_SIZE; 00233 } 00234 #endif 00235 } 00236 00237 if ( XSTRNCMP((const char*)sender, (const char*)client, SIZEOF_SENDER) == 0) 00238 side = tls_client; 00239 else 00240 side = tls_server; 00241 00242 #ifndef NO_MD5 00243 PRF(hashes->md5, TLS_FINISHED_SZ, ssl->arrays->masterSecret, SECRET_LEN, 00244 side, FINISHED_LABEL_SZ, handshake_hash, hashSz, IsAtLeastTLSv1_2(ssl), 00245 ssl->specs.mac_algorithm); 00246 #else 00247 PRF(hashes->hash, TLS_FINISHED_SZ, ssl->arrays->masterSecret, SECRET_LEN, 00248 side, FINISHED_LABEL_SZ, handshake_hash, hashSz, IsAtLeastTLSv1_2(ssl), 00249 ssl->specs.mac_algorithm); 00250 #endif 00251 } 00252 00253 00254 #ifndef NO_OLD_TLS 00255 00256 ProtocolVersion MakeTLSv1(void) 00257 { 00258 ProtocolVersion pv; 00259 pv.major = SSLv3_MAJOR; 00260 pv.minor = TLSv1_MINOR; 00261 00262 return pv; 00263 } 00264 00265 00266 ProtocolVersion MakeTLSv1_1(void) 00267 { 00268 ProtocolVersion pv; 00269 pv.major = SSLv3_MAJOR; 00270 pv.minor = TLSv1_1_MINOR; 00271 00272 return pv; 00273 } 00274 00275 #endif 00276 00277 00278 ProtocolVersion MakeTLSv1_2(void) 00279 { 00280 ProtocolVersion pv; 00281 pv.major = SSLv3_MAJOR; 00282 pv.minor = TLSv1_2_MINOR; 00283 00284 return pv; 00285 } 00286 00287 00288 static const byte master_label[MASTER_LABEL_SZ + 1] = "master secret"; 00289 static const byte key_label [KEY_LABEL_SZ + 1] = "key expansion"; 00290 00291 00292 int DeriveTlsKeys(CYASSL* ssl) 00293 { 00294 int length = 2 * ssl->specs.hash_size + 00295 2 * ssl->specs.key_size + 00296 2 * ssl->specs.iv_size; 00297 byte seed[SEED_LEN]; 00298 byte key_data[MAX_PRF_DIG]; 00299 00300 XMEMCPY(seed, ssl->arrays->serverRandom, RAN_LEN); 00301 XMEMCPY(&seed[RAN_LEN], ssl->arrays->clientRandom, RAN_LEN); 00302 00303 PRF(key_data, length, ssl->arrays->masterSecret, SECRET_LEN, key_label, 00304 KEY_LABEL_SZ, seed, SEED_LEN, IsAtLeastTLSv1_2(ssl), 00305 ssl->specs.mac_algorithm); 00306 00307 return StoreKeys(ssl, key_data); 00308 } 00309 00310 00311 int MakeTlsMasterSecret(CYASSL* ssl) 00312 { 00313 byte seed[SEED_LEN]; 00314 00315 XMEMCPY(seed, ssl->arrays->clientRandom, RAN_LEN); 00316 XMEMCPY(&seed[RAN_LEN], ssl->arrays->serverRandom, RAN_LEN); 00317 00318 PRF(ssl->arrays->masterSecret, SECRET_LEN, 00319 ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz, 00320 master_label, MASTER_LABEL_SZ, 00321 seed, SEED_LEN, IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm); 00322 00323 #ifdef SHOW_SECRETS 00324 { 00325 int i; 00326 printf("master secret: "); 00327 for (i = 0; i < SECRET_LEN; i++) 00328 printf("%02x", ssl->arrays->masterSecret[i]); 00329 printf("\n"); 00330 } 00331 #endif 00332 00333 return DeriveTlsKeys(ssl); 00334 } 00335 00336 00337 /*** next for static INLINE s copied from cyassl_int.c ***/ 00338 00339 /* convert 16 bit integer to opaque */ 00340 INLINE static void c16toa(word16 u16, byte* c) 00341 { 00342 c[0] = (u16 >> 8) & 0xff; 00343 c[1] = u16 & 0xff; 00344 } 00345 00346 00347 /* convert 32 bit integer to opaque */ 00348 static INLINE void c32toa(word32 u32, byte* c) 00349 { 00350 c[0] = (u32 >> 24) & 0xff; 00351 c[1] = (u32 >> 16) & 0xff; 00352 c[2] = (u32 >> 8) & 0xff; 00353 c[3] = u32 & 0xff; 00354 } 00355 00356 00357 static INLINE word32 GetSEQIncrement(CYASSL* ssl, int verify) 00358 { 00359 #ifdef CYASSL_DTLS 00360 if (ssl->options.dtls) { 00361 if (verify) 00362 return ssl->keys.dtls_peer_sequence_number; /* explicit from peer */ 00363 else 00364 return ssl->keys.dtls_sequence_number - 1; /* already incremented */ 00365 } 00366 #endif 00367 if (verify) 00368 return ssl->keys.peer_sequence_number++; 00369 else 00370 return ssl->keys.sequence_number++; 00371 } 00372 00373 00374 #ifdef CYASSL_DTLS 00375 00376 static INLINE word32 GetEpoch(CYASSL* ssl, int verify) 00377 { 00378 if (verify) 00379 return ssl->keys.dtls_peer_epoch; 00380 else 00381 return ssl->keys.dtls_epoch; 00382 } 00383 00384 #endif /* CYASSL_DTLS */ 00385 00386 00387 static INLINE const byte* GetMacSecret(CYASSL* ssl, int verify) 00388 { 00389 if ( (ssl->options.side == CLIENT_END && !verify) || 00390 (ssl->options.side == SERVER_END && verify) ) 00391 return ssl->keys.client_write_MAC_secret; 00392 else 00393 return ssl->keys.server_write_MAC_secret; 00394 } 00395 00396 /*** end copy ***/ 00397 00398 00399 /* TLS type HMAC */ 00400 void TLS_hmac(CYASSL* ssl, byte* digest, const byte* in, word32 sz, 00401 int content, int verify) 00402 { 00403 Hmac hmac; 00404 byte seq[SEQ_SZ]; 00405 byte length[LENGTH_SZ]; 00406 byte inner[ENUM_LEN + VERSION_SZ + LENGTH_SZ]; /* type + version +len */ 00407 int type; 00408 00409 XMEMSET(seq, 0, SEQ_SZ); 00410 c16toa((word16)sz, length); 00411 #ifdef CYASSL_DTLS 00412 if (ssl->options.dtls) 00413 c16toa((word16)GetEpoch(ssl, verify), seq); 00414 #endif 00415 c32toa(GetSEQIncrement(ssl, verify), &seq[sizeof(word32)]); 00416 00417 switch (ssl->specs.mac_algorithm) { 00418 #ifndef NO_MD5 00419 case md5_mac: 00420 { 00421 type = MD5; 00422 } 00423 break; 00424 #endif 00425 #ifndef NO_SHA256 00426 case sha256_mac: 00427 { 00428 type = SHA256; 00429 } 00430 break; 00431 #endif 00432 case sha_mac: 00433 default: 00434 { 00435 type = SHA; 00436 } 00437 break; 00438 } 00439 HmacSetKey(&hmac, type, GetMacSecret(ssl, verify), ssl->specs.hash_size); 00440 00441 HmacUpdate(&hmac, seq, SEQ_SZ); /* seq_num */ 00442 inner[0] = (byte)content; /* type */ 00443 inner[ENUM_LEN] = ssl->version.major; 00444 inner[ENUM_LEN + ENUM_LEN] = ssl->version.minor; /* version */ 00445 XMEMCPY(&inner[ENUM_LEN + VERSION_SZ], length, LENGTH_SZ); /* length */ 00446 HmacUpdate(&hmac, inner, sizeof(inner)); 00447 HmacUpdate(&hmac, in, sz); /* content */ 00448 HmacFinal(&hmac, digest); 00449 } 00450 00451 00452 #ifndef NO_CYASSL_CLIENT 00453 00454 #ifndef NO_OLD_TLS 00455 00456 CYASSL_METHOD* CyaTLSv1_client_method(void) 00457 { 00458 CYASSL_METHOD* method = 00459 (CYASSL_METHOD*) XMALLOC(sizeof(CYASSL_METHOD), 0, 00460 DYNAMIC_TYPE_METHOD); 00461 if (method) 00462 InitSSL_Method(method, MakeTLSv1()); 00463 return method; 00464 } 00465 00466 00467 CYASSL_METHOD* CyaTLSv1_1_client_method(void) 00468 { 00469 CYASSL_METHOD* method = 00470 (CYASSL_METHOD*) XMALLOC(sizeof(CYASSL_METHOD), 0, 00471 DYNAMIC_TYPE_METHOD); 00472 if (method) 00473 InitSSL_Method(method, MakeTLSv1_1()); 00474 return method; 00475 } 00476 00477 #endif /* !NO_OLD_TLS */ 00478 00479 #ifndef NO_SHA256 /* can't use without SHA256 */ 00480 00481 CYASSL_METHOD* CyaTLSv1_2_client_method(void) 00482 { 00483 CYASSL_METHOD* method = 00484 (CYASSL_METHOD*) XMALLOC(sizeof(CYASSL_METHOD), 0, 00485 DYNAMIC_TYPE_METHOD); 00486 if (method) 00487 InitSSL_Method(method, MakeTLSv1_2()); 00488 return method; 00489 } 00490 00491 #endif 00492 00493 00494 CYASSL_METHOD* CyaSSLv23_client_method(void) 00495 { 00496 CYASSL_METHOD* method = 00497 (CYASSL_METHOD*) XMALLOC(sizeof(CYASSL_METHOD), 0, 00498 DYNAMIC_TYPE_METHOD); 00499 if (method) { 00500 #ifndef NO_SHA256 /* 1.2 requires SHA256 */ 00501 InitSSL_Method(method, MakeTLSv1_2()); 00502 #else 00503 InitSSL_Method(method, MakeTLSv1_1()); 00504 #endif 00505 #ifndef NO_OLD_TLS 00506 method->downgrade = 1; 00507 #endif 00508 } 00509 return method; 00510 } 00511 00512 00513 #endif /* NO_CYASSL_CLIENT */ 00514 00515 00516 00517 #ifndef NO_CYASSL_SERVER 00518 00519 #ifndef NO_OLD_TLS 00520 00521 CYASSL_METHOD* CyaTLSv1_server_method(void) 00522 { 00523 CYASSL_METHOD* method = 00524 (CYASSL_METHOD*) XMALLOC(sizeof(CYASSL_METHOD), 0, 00525 DYNAMIC_TYPE_METHOD); 00526 if (method) { 00527 InitSSL_Method(method, MakeTLSv1()); 00528 method->side = SERVER_END; 00529 } 00530 return method; 00531 } 00532 00533 00534 CYASSL_METHOD* CyaTLSv1_1_server_method(void) 00535 { 00536 CYASSL_METHOD* method = 00537 (CYASSL_METHOD*) XMALLOC(sizeof(CYASSL_METHOD), 0, 00538 DYNAMIC_TYPE_METHOD); 00539 if (method) { 00540 InitSSL_Method(method, MakeTLSv1_1()); 00541 method->side = SERVER_END; 00542 } 00543 return method; 00544 } 00545 00546 #endif /* !NO_OLD_TLS */ 00547 00548 #ifndef NO_SHA256 /* can't use without SHA256 */ 00549 00550 CYASSL_METHOD* CyaTLSv1_2_server_method(void) 00551 { 00552 CYASSL_METHOD* method = 00553 (CYASSL_METHOD*) XMALLOC(sizeof(CYASSL_METHOD), 0, 00554 DYNAMIC_TYPE_METHOD); 00555 if (method) { 00556 InitSSL_Method(method, MakeTLSv1_2()); 00557 method->side = SERVER_END; 00558 } 00559 return method; 00560 } 00561 00562 #endif 00563 00564 00565 CYASSL_METHOD* CyaSSLv23_server_method(void) 00566 { 00567 CYASSL_METHOD* method = 00568 (CYASSL_METHOD*) XMALLOC(sizeof(CYASSL_METHOD), 0, 00569 DYNAMIC_TYPE_METHOD); 00570 if (method) { 00571 #ifndef NO_SHA256 /* 1.2 requires SHA256 */ 00572 InitSSL_Method(method, MakeTLSv1_2()); 00573 #else 00574 InitSSL_Method(method, MakeTLSv1_1()); 00575 #endif 00576 method->side = SERVER_END; 00577 #ifndef NO_OLD_TLS 00578 method->downgrade = 1; 00579 #endif /* !NO_OLD_TLS */ 00580 } 00581 return method; 00582 } 00583 00584 00585 00586 #endif /* NO_CYASSL_SERVER */ 00587 00588 #else /* NO_TLS */ 00589 00590 /* catch CyaSSL programming errors */ 00591 void BuildTlsFinished(CYASSL* ssl, Hashes* hashes, const byte* sender) 00592 { 00593 00594 } 00595 00596 00597 int DeriveTlsKeys(CYASSL* ssl) 00598 { 00599 return NOT_COMPILED_IN; 00600 } 00601 00602 00603 int MakeTlsMasterSecret(CYASSL* ssl) 00604 { 00605 return NOT_COMPILED_IN; 00606 } 00607 00608 #endif /* NO_TLS */ 00609
Generated on Thu Jul 14 2022 00:25:24 by 1.7.2