Webserver+3d print
Embed:
(wiki syntax)
Show/hide line numbers
tls.c
Go to the documentation of this file.
00001 /** 00002 * @file tls.c 00003 * @brief TLS (Transport Layer Security) 00004 * 00005 * @section License 00006 * 00007 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved. 00008 * 00009 * This file is part of CycloneSSL Open. 00010 * 00011 * This program is free software; you can redistribute it and/or 00012 * modify it under the terms of the GNU General Public License 00013 * as published by the Free Software Foundation; either version 2 00014 * of the License, or (at your option) any later version. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU General Public License 00022 * along with this program; if not, write to the Free Software Foundation, 00023 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00024 * 00025 * @section Description 00026 * 00027 * The TLS protocol provides communications security over the Internet. The 00028 * protocol allows client/server applications to communicate in a way that 00029 * is designed to prevent eavesdropping, tampering, or message forgery 00030 * 00031 * @author Oryx Embedded SARL (www.oryx-embedded.com) 00032 * @version 1.7.6 00033 **/ 00034 00035 //Switch to the appropriate trace level 00036 #define TRACE_LEVEL TLS_TRACE_LEVEL 00037 00038 //Dependencies 00039 #include <string.h> 00040 #include <ctype.h> 00041 #include "tls.h" 00042 #include "tls_client.h" 00043 #include "tls_server.h" 00044 #include "tls_common.h" 00045 #include "tls_record.h" 00046 #include "tls_misc.h" 00047 #include "x509.h" 00048 #include "pem.h" 00049 #include "debug.h" 00050 00051 //Check SSL library configuration 00052 #if (TLS_SUPPORT == ENABLED) 00053 00054 00055 /** 00056 * @brief TLS context initialization 00057 * @return Handle referencing the fully initialized TLS context 00058 **/ 00059 00060 TlsContext *tlsInit(void) 00061 { 00062 TlsContext *context; 00063 00064 //Allocate a memory buffer to hold the TLS context 00065 context = tlsAllocMem(sizeof(TlsContext)); 00066 00067 //Successful memory allocation? 00068 if(context != NULL) 00069 { 00070 //Clear TLS context 00071 memset(context, 0, sizeof(TlsContext)); 00072 00073 //Default state 00074 context->state = TLS_STATE_INIT; 00075 //Default operation mode 00076 context->entity = TLS_CONNECTION_END_CLIENT; 00077 //Default TLS version 00078 context->version = TLS_MIN_VERSION; 00079 //Default client authentication mode 00080 context->clientAuthMode = TLS_CLIENT_AUTH_NONE; 00081 00082 #if (TLS_DH_ANON_SUPPORT == ENABLED || TLS_DHE_RSA_SUPPORT == ENABLED || \ 00083 TLS_DHE_DSS_SUPPORT == ENABLED || TLS_DHE_PSK_SUPPORT == ENABLED) 00084 //Initialize Diffie-Hellman context 00085 dhInit(&context->dhContext); 00086 #endif 00087 00088 #if (TLS_ECDH_ANON_SUPPORT == ENABLED || TLS_ECDHE_RSA_SUPPORT == ENABLED || \ 00089 TLS_ECDHE_ECDSA_SUPPORT == ENABLED || TLS_ECDHE_PSK_SUPPORT == ENABLED) 00090 //Initialize ECDH context 00091 ecdhInit(&context->ecdhContext); 00092 #endif 00093 00094 #if (TLS_RSA_SIGN_SUPPORT == ENABLED || TLS_RSA_SUPPORT == ENABLED || \ 00095 TLS_DHE_RSA_SUPPORT == ENABLED || TLS_ECDHE_RSA_SUPPORT == ENABLED) 00096 //Initialize peer's RSA public key 00097 rsaInitPublicKey(&context->peerRsaPublicKey); 00098 #endif 00099 00100 #if (TLS_DSA_SIGN_SUPPORT == ENABLED || TLS_DHE_DSS_SUPPORT == ENABLED) 00101 //Initialize peer's DSA public key 00102 dsaInitPublicKey(&context->peerDsaPublicKey); 00103 #endif 00104 00105 #if (TLS_ECDSA_SIGN_SUPPORT == ENABLED || TLS_ECDHE_ECDSA_SUPPORT == ENABLED) 00106 //Initialize peer's EC domain parameters 00107 ecInitDomainParameters(&context->peerEcParams); 00108 //Initialize peer's EC public key 00109 ecInit(&context->peerEcPublicKey); 00110 #endif 00111 00112 //Set the maximum fragment length for outgoing TLS records 00113 context->txRecordMaxLen = TLS_MAX_RECORD_LENGTH; 00114 00115 //Compute the corresponding buffer size 00116 context->txBufferSize = TLS_MAX_RECORD_LENGTH + 00117 sizeof(TlsRecord) + TLS_MAX_RECORD_OVERHEAD; 00118 00119 //Save the maximum fragment length for incoming TLS records 00120 context->rxRecordMaxLen = TLS_MAX_RECORD_LENGTH; 00121 00122 //Compute the corresponding buffer size 00123 context->rxBufferSize = TLS_MAX_RECORD_LENGTH + 00124 sizeof(TlsRecord) + TLS_MAX_RECORD_OVERHEAD; 00125 } 00126 00127 //Return a pointer to the freshly created TLS context 00128 return context; 00129 } 00130 00131 00132 /** 00133 * @brief Set send and receive callbacks (I/O abstraction layer) 00134 * @param[in] context Pointer to the TLS context 00135 * @param[in] handle Handle for I/O operations 00136 * @param[in] sendCallback Send callback function 00137 * @param[in] receiveCallback Receive callback function 00138 * @return Error code 00139 **/ 00140 00141 error_t tlsSetIoCallbacks(TlsContext *context, TlsIoHandle handle, 00142 TlsIoSendCallback sendCallback, TlsIoReceiveCallback receiveCallback) 00143 { 00144 //Check parameters 00145 if(context == NULL || sendCallback == NULL || receiveCallback == NULL) 00146 return ERROR_INVALID_PARAMETER; 00147 00148 //Save I/O handle 00149 context->handle = handle; 00150 00151 //Save send and receive callback functions 00152 context->sendCallback = sendCallback; 00153 context->receiveCallback = receiveCallback; 00154 00155 //Successful processing 00156 return NO_ERROR; 00157 } 00158 00159 00160 /** 00161 * @brief Set operation mode (client or server) 00162 * @param[in] context Pointer to the TLS context 00163 * @param[in] entity Specifies whether this entity is considered a client or a server 00164 * @return Error code 00165 **/ 00166 00167 error_t tlsSetConnectionEnd(TlsContext *context, TlsConnectionEnd entity) 00168 { 00169 //Invalid TLS context? 00170 if(context == NULL) 00171 return ERROR_INVALID_PARAMETER; 00172 //Invalid parameter? 00173 if(entity != TLS_CONNECTION_END_CLIENT && entity != TLS_CONNECTION_END_SERVER) 00174 return ERROR_INVALID_PARAMETER; 00175 00176 //Check whether TLS operates as a client or a server 00177 context->entity = entity; 00178 00179 //Successful processing 00180 return NO_ERROR; 00181 } 00182 00183 00184 /** 00185 * @brief Set the pseudo-random number generator to be used 00186 * @param[in] context Pointer to the TLS context 00187 * @param[in] prngAlgo PRNG algorithm 00188 * @param[in] prngContext Pointer to the PRNG context 00189 * @return Error code 00190 **/ 00191 00192 error_t tlsSetPrng(TlsContext *context, const PrngAlgo *prngAlgo, void *prngContext) 00193 { 00194 //Invalid TLS context? 00195 if(context == NULL) 00196 return ERROR_INVALID_PARAMETER; 00197 //Invalid parameters? 00198 if(prngAlgo == NULL || prngContext == NULL) 00199 return ERROR_INVALID_PARAMETER; 00200 00201 //PRNG algorithm that will be used to generate random numbers 00202 context->prngAlgo = prngAlgo; 00203 //PRNG context 00204 context->prngContext = prngContext; 00205 00206 //Successful processing 00207 return NO_ERROR; 00208 } 00209 00210 00211 /** 00212 * @brief Set the name of the remote server 00213 * @param[in] context Pointer to the TLS context 00214 * @param[in] serverName Fully qualified domain name of the server 00215 * @return Error code 00216 **/ 00217 00218 error_t tlsSetServerName(TlsContext *context, const char_t *serverName) 00219 { 00220 size_t i; 00221 size_t length; 00222 00223 //Invalid parameters? 00224 if(context == NULL || serverName == NULL) 00225 return ERROR_INVALID_PARAMETER; 00226 00227 //Retrieve the length of the server name 00228 length = strlen(serverName); 00229 00230 //Check whether the server name has already been configured 00231 if(context->serverName != NULL) 00232 { 00233 //Release memory 00234 tlsFreeMem(context->serverName); 00235 context->serverName = NULL; 00236 } 00237 00238 //Valid server name? 00239 if(length > 0) 00240 { 00241 //Allocate a memory block to hold the hostname 00242 context->serverName = tlsAllocMem(length + 1); 00243 //Failed to allocate memory? 00244 if(context->serverName == NULL) 00245 return ERROR_OUT_OF_MEMORY; 00246 00247 //Convert the hostname into lowercase 00248 for(i = 0; i < length; i++) 00249 context->serverName[i] = tolower((uint8_t) serverName[i]); 00250 00251 //Properly terminate the string with a NULL character 00252 context->serverName[length] = '\0'; 00253 } 00254 00255 //Successful processing 00256 return NO_ERROR; 00257 } 00258 00259 00260 /** 00261 * @brief Set session cache 00262 * @param[in] context Pointer to the TLS context 00263 * @param[in] cache Session cache that will be used to save/resume TLS sessions 00264 * @return Error code 00265 **/ 00266 00267 error_t tlsSetCache(TlsContext *context, TlsCache *cache) 00268 { 00269 //Check parameters 00270 if(context == NULL || cache == NULL) 00271 return ERROR_INVALID_PARAMETER; 00272 00273 //The cache will be used to save/resume TLS sessions 00274 context->cache = cache; 00275 00276 //Successful processing 00277 return NO_ERROR; 00278 } 00279 00280 00281 /** 00282 * @brief Set client authentication mode 00283 * @param[in] context Pointer to the TLS context 00284 * @param[in] mode Client authentication mode 00285 * @return Error code 00286 **/ 00287 00288 error_t tlsSetClientAuthMode(TlsContext *context, TlsClientAuthMode mode) 00289 { 00290 //Invalid TLS context? 00291 if(context == NULL) 00292 return ERROR_INVALID_PARAMETER; 00293 00294 //Save client authentication mode 00295 context->clientAuthMode = mode; 00296 00297 //Successful processing 00298 return NO_ERROR; 00299 } 00300 00301 00302 /** 00303 * @brief Set TLS buffer size 00304 * @param[in] context Pointer to the TLS context 00305 * @param[in] txBufferSize TX buffer size 00306 * @param[in] rxBufferSize RX buffer size 00307 * @return Error code 00308 **/ 00309 00310 error_t tlsSetBufferSize(TlsContext *context, 00311 size_t txBufferSize, size_t rxBufferSize) 00312 { 00313 //Invalid TLS context? 00314 if(context == NULL) 00315 return ERROR_INVALID_PARAMETER; 00316 //Check parameters 00317 if(txBufferSize < 512 || rxBufferSize < 512) 00318 return ERROR_INVALID_PARAMETER; 00319 00320 //Save the maximum fragment length for outgoing TLS records 00321 context->txRecordMaxLen = txBufferSize; 00322 00323 //Compute the corresponding buffer size 00324 context->txBufferSize = txBufferSize + 00325 sizeof(TlsRecord) + TLS_MAX_RECORD_OVERHEAD; 00326 00327 //Save the maximum fragment length for incoming TLS records 00328 context->rxRecordMaxLen = rxBufferSize; 00329 00330 //Compute the corresponding buffer size 00331 context->rxBufferSize = rxBufferSize + 00332 sizeof(TlsRecord) + TLS_MAX_RECORD_OVERHEAD; 00333 00334 //Successful processing 00335 return NO_ERROR; 00336 } 00337 00338 00339 /** 00340 * @brief Specify the list of allowed cipher suites 00341 * @param[in] context Pointer to the TLS context 00342 * @param[in] cipherSuites Pointer to the cipher suite list 00343 * @param[in] length Number of cipher suites in the list 00344 * @return Error code 00345 **/ 00346 00347 error_t tlsSetCipherSuites(TlsContext *context, 00348 const uint16_t *cipherSuites, uint_t length) 00349 { 00350 //Invalid TLS context? 00351 if(context == NULL) 00352 return ERROR_INVALID_PARAMETER; 00353 //Check parameters 00354 if(cipherSuites == NULL && length != 0) 00355 return ERROR_INVALID_PARAMETER; 00356 00357 //Restrict the cipher suites that can be used 00358 context->cipherSuites = cipherSuites; 00359 context->numCipherSuites = length; 00360 00361 //Successful processing 00362 return NO_ERROR; 00363 } 00364 00365 00366 /** 00367 * @brief Import Diffie-Hellman parameters 00368 * @param[in] context Pointer to the TLS context 00369 * @param[in] params PEM structure that holds Diffie-Hellman parameters 00370 * @param[in] length Total length of the DER structure 00371 * @return Error code 00372 **/ 00373 00374 error_t tlsSetDhParameters(TlsContext *context, 00375 const char_t *params, size_t length) 00376 { 00377 #if (TLS_DH_ANON_SUPPORT == ENABLED || TLS_DHE_RSA_SUPPORT == ENABLED || \ 00378 TLS_DHE_DSS_SUPPORT == ENABLED || TLS_DHE_PSK_SUPPORT == ENABLED) 00379 //Invalid TLS context? 00380 if(context == NULL) 00381 return ERROR_INVALID_PARAMETER; 00382 //Check parameters 00383 if(params == NULL && length != 0) 00384 return ERROR_INVALID_PARAMETER; 00385 00386 //Decode the PEM structure that holds Diffie-Hellman parameters 00387 return pemReadDhParameters(params, length, &context->dhContext.params); 00388 #else 00389 //Diffie-Hellman is not implemented 00390 return ERROR_NOT_IMPLEMENTED; 00391 #endif 00392 } 00393 00394 00395 /** 00396 * @brief Set the list of supported ALPN protocols 00397 * @param[in] context Pointer to the TLS context 00398 * @param[in] protocolList Comma-delimited list of supported protocols 00399 * @return Error code 00400 **/ 00401 00402 error_t tlsSetAlpnProtocolList(TlsContext *context, const char_t *protocolList) 00403 { 00404 #if (TLS_ALPN_SUPPORT == ENABLED) 00405 size_t length; 00406 00407 //Invalid parameters? 00408 if(context == NULL || protocolList == NULL) 00409 return ERROR_INVALID_PARAMETER; 00410 00411 //Retrieve the length of the list 00412 length = strlen(protocolList); 00413 00414 //Check whether the list of supported protocols has already been configured 00415 if(context->protocolList != NULL) 00416 { 00417 //Release memory 00418 tlsFreeMem(context->protocolList); 00419 context->protocolList = NULL; 00420 } 00421 00422 //Check whether the list of protocols is valid 00423 if(length > 0) 00424 { 00425 //Allocate a memory block to hold the list 00426 context->protocolList = tlsAllocMem(length + 1); 00427 //Failed to allocate memory? 00428 if(context->protocolList == NULL) 00429 return ERROR_OUT_OF_MEMORY; 00430 00431 //Save the list of supported protocols 00432 strcpy(context->protocolList, protocolList); 00433 } 00434 00435 //Successful processing 00436 return NO_ERROR; 00437 #else 00438 //ALPN is not implemented 00439 return ERROR_NOT_IMPLEMENTED; 00440 #endif 00441 } 00442 00443 00444 /** 00445 * @brief Get the name of the negotiated ALPN protocol 00446 * @param[in] context Pointer to the TLS context 00447 * @return Pointer to the protocol name 00448 **/ 00449 00450 const char_t *tlsGetAlpnProtocol(TlsContext *context) 00451 { 00452 //Not implemented 00453 return NULL; 00454 } 00455 00456 00457 /** 00458 * @brief Set the pre-shared key to be used 00459 * @param[in] context Pointer to the TLS context 00460 * @param[in] psk Pointer to the pre-shared key 00461 * @param[in] pskLength Length of the pre-shared key, in bytes 00462 * @return Error code 00463 **/ 00464 00465 error_t tlsSetPsk(TlsContext *context, const uint8_t *psk, size_t pskLength) 00466 { 00467 #if (TLS_PSK_SUPPORT == ENABLED || TLS_RSA_PSK_SUPPORT == ENABLED || \ 00468 TLS_DHE_PSK_SUPPORT == ENABLED || TLS_ECDHE_PSK_SUPPORT == ENABLED) 00469 //Invalid TLS context? 00470 if(context == NULL) 00471 return ERROR_INVALID_PARAMETER; 00472 //Check parameters 00473 if(psk == NULL && pskLength != 0) 00474 return ERROR_INVALID_PARAMETER; 00475 00476 //Check whether the pre-shared key has already been configured 00477 if(context->psk != NULL) 00478 { 00479 //Release memory 00480 memset(context->psk, 0, context->pskLen); 00481 tlsFreeMem(context->psk); 00482 //Re-initialize length 00483 context->pskLen = 0; 00484 } 00485 00486 //Valid PSK? 00487 if(pskLength > 0) 00488 { 00489 //Allocate a memory block to hold the pre-shared key 00490 context->psk = tlsAllocMem(pskLength); 00491 //Failed to allocate memory? 00492 if(context->psk == NULL) 00493 return ERROR_OUT_OF_MEMORY; 00494 00495 //Save the pre-shared key 00496 memcpy(context->psk, psk, pskLength); 00497 //Save the length of the key 00498 context->pskLen = pskLength; 00499 } 00500 00501 //Successful processing 00502 return NO_ERROR; 00503 #else 00504 //PSK key exchange is not implemented 00505 return ERROR_NOT_IMPLEMENTED; 00506 #endif 00507 } 00508 00509 00510 /** 00511 * @brief Set the PSK identity to be used by the client 00512 * @param[in] context Pointer to the TLS context 00513 * @param[in] pskIdentity NULL-terminated string that contains the PSK identity 00514 * @return Error code 00515 **/ 00516 00517 error_t tlsSetPskIdentity(TlsContext *context, const char_t *pskIdentity) 00518 { 00519 #if (TLS_PSK_SUPPORT == ENABLED || TLS_RSA_PSK_SUPPORT == ENABLED || \ 00520 TLS_DHE_PSK_SUPPORT == ENABLED || TLS_ECDHE_PSK_SUPPORT == ENABLED) 00521 size_t length; 00522 00523 //Invalid parameters? 00524 if(context == NULL || pskIdentity == NULL) 00525 return ERROR_INVALID_PARAMETER; 00526 00527 //Retrieve the length of the PSK identity 00528 length = strlen(pskIdentity); 00529 00530 //Check whether the PSK identity has already been configured 00531 if(context->pskIdentity != NULL) 00532 { 00533 //Release memory 00534 tlsFreeMem(context->pskIdentity); 00535 context->pskIdentity = NULL; 00536 } 00537 00538 //Valid PSK identity? 00539 if(length > 0) 00540 { 00541 //Allocate a memory block to hold the PSK identity 00542 context->pskIdentity = tlsAllocMem(length + 1); 00543 //Failed to allocate memory? 00544 if(context->pskIdentity == NULL) 00545 return ERROR_OUT_OF_MEMORY; 00546 00547 //Save the PSK identity 00548 strcpy(context->pskIdentity, pskIdentity); 00549 } 00550 00551 //Successful processing 00552 return NO_ERROR; 00553 #else 00554 //PSK key exchange is not implemented 00555 return ERROR_NOT_IMPLEMENTED; 00556 #endif 00557 } 00558 00559 00560 /** 00561 * @brief Set the PSK identity hint to be used by the server 00562 * @param[in] context Pointer to the TLS context 00563 * @param[in] pskIdentityHint NULL-terminated string that contains the PSK identity hint 00564 * @return Error code 00565 **/ 00566 00567 error_t tlsSetPskIdentityHint(TlsContext *context, const char_t *pskIdentityHint) 00568 { 00569 #if (TLS_PSK_SUPPORT == ENABLED || TLS_RSA_PSK_SUPPORT == ENABLED || \ 00570 TLS_DHE_PSK_SUPPORT == ENABLED || TLS_ECDHE_PSK_SUPPORT == ENABLED) 00571 size_t length; 00572 00573 //Invalid parameters? 00574 if(context == NULL || pskIdentityHint == NULL) 00575 return ERROR_INVALID_PARAMETER; 00576 00577 //Retrieve the length of the PSK identity hint 00578 length = strlen(pskIdentityHint); 00579 00580 //Check whether the PSK identity hint has already been configured 00581 if(context->pskIdentityHint != NULL) 00582 { 00583 //Release memory 00584 tlsFreeMem(context->pskIdentityHint); 00585 context->pskIdentityHint = NULL; 00586 } 00587 00588 //Valid PSK identity hint? 00589 if(length > 0) 00590 { 00591 //Allocate a memory block to hold the PSK identity hint 00592 context->pskIdentityHint = tlsAllocMem(length + 1); 00593 //Failed to allocate memory? 00594 if(context->pskIdentityHint == NULL) 00595 return ERROR_OUT_OF_MEMORY; 00596 00597 //Save the PSK identity hint 00598 strcpy(context->pskIdentityHint, pskIdentityHint); 00599 } 00600 00601 //Successful processing 00602 return NO_ERROR; 00603 #else 00604 //PSK key exchange is not implemented 00605 return ERROR_NOT_IMPLEMENTED; 00606 #endif 00607 } 00608 00609 00610 /** 00611 * @brief Register the PSK callback function 00612 * @param[in] context Pointer to the TLS context 00613 * @param[in] pskCallback PSK callback function 00614 * @return Error code 00615 **/ 00616 00617 error_t tlsSetPskCallback(TlsContext *context, TlsPskCallback pskCallback) 00618 { 00619 #if (TLS_PSK_SUPPORT == ENABLED || TLS_RSA_PSK_SUPPORT == ENABLED || \ 00620 TLS_DHE_PSK_SUPPORT == ENABLED || TLS_ECDHE_PSK_SUPPORT == ENABLED) 00621 //Invalid parameters? 00622 if(context == NULL || pskCallback == NULL) 00623 return ERROR_INVALID_PARAMETER; 00624 00625 //Save the PSK callback function 00626 context->pskCallback = pskCallback; 00627 00628 //Successful processing 00629 return NO_ERROR; 00630 #else 00631 //PSK key exchange is not implemented 00632 return ERROR_NOT_IMPLEMENTED; 00633 #endif 00634 } 00635 00636 00637 /** 00638 * @brief Import a trusted CA list 00639 * @param[in] context Pointer to the TLS context 00640 * @param[in] trustedCaList List of trusted CA (PEM format) 00641 * @param[in] length Total length of the list 00642 * @return Error code 00643 **/ 00644 00645 error_t tlsSetTrustedCaList(TlsContext *context, 00646 const char_t *trustedCaList, size_t length) 00647 { 00648 //Invalid TLS context? 00649 if(context == NULL) 00650 return ERROR_INVALID_PARAMETER; 00651 //Check parameters 00652 if(trustedCaList == NULL && length != 0) 00653 return ERROR_INVALID_PARAMETER; 00654 00655 //Save the certificate chain 00656 context->trustedCaList = trustedCaList; 00657 context->trustedCaListLen = length; 00658 00659 //Successful processing 00660 return NO_ERROR; 00661 } 00662 00663 00664 /** 00665 * @brief Import a certificate and the corresponding private key 00666 * @param[in] context Pointer to the TLS context 00667 * @param[in] certChain Certificate chain (PEM format) 00668 * @param[in] certChainLength Total length of the certificate chain 00669 * @param[in] privateKey Private key (PEM format) 00670 * @param[in] privateKeyLength Total length of the private key 00671 * @return Error code 00672 **/ 00673 00674 error_t tlsAddCertificate(TlsContext *context, const char_t *certChain, 00675 size_t certChainLength, const char_t *privateKey, size_t privateKeyLength) 00676 { 00677 error_t error; 00678 const char_t *p; 00679 size_t n; 00680 uint8_t *derCert; 00681 size_t derCertSize; 00682 size_t derCertLength; 00683 X509CertificateInfo *certInfo; 00684 TlsCertificateType certType; 00685 TlsSignatureAlgo certSignAlgo; 00686 TlsHashAlgo certHashAlgo; 00687 TlsEcNamedCurve namedCurve; 00688 00689 //Invalid TLS context? 00690 if(context == NULL) 00691 return ERROR_INVALID_PARAMETER; 00692 00693 //Check parameters 00694 if(certChain == NULL || certChainLength == 0) 00695 return ERROR_INVALID_PARAMETER; 00696 if(privateKey == NULL || privateKeyLength == 0) 00697 return ERROR_INVALID_PARAMETER; 00698 00699 //Make sure there is enough room to add the certificate 00700 if(context->numCerts >= TLS_MAX_CERTIFICATES) 00701 return ERROR_OUT_OF_RESOURCES; 00702 00703 //Allocate a memory buffer to store X.509 certificate info 00704 certInfo = tlsAllocMem(sizeof(X509CertificateInfo)); 00705 //Failed to allocate memory? 00706 if(certInfo == NULL) 00707 return ERROR_OUT_OF_MEMORY; 00708 00709 //Point to the beginning of the certificate chain 00710 p = certChain; 00711 n = certChainLength; 00712 00713 //DER encoded certificate 00714 derCert = NULL; 00715 derCertSize = 0; 00716 derCertLength = 0; 00717 00718 //Start of exception handling block 00719 do 00720 { 00721 //Decode end entity certificate 00722 error = pemReadCertificate(&p, &n, &derCert, &derCertSize, &derCertLength); 00723 //Any error to report? 00724 if(error) 00725 break; 00726 00727 //Parse X.509 certificate 00728 error = x509ParseCertificate(derCert, derCertLength, certInfo); 00729 //Failed to parse the X.509 certificate? 00730 if(error) 00731 break; 00732 00733 //Retrieve the signature algorithm that has been used to sign the certificate 00734 error = tlsGetCertificateType(certInfo, &certType, 00735 &certSignAlgo, &certHashAlgo, &namedCurve); 00736 //The specified signature algorithm is not supported? 00737 if(error) 00738 break; 00739 00740 //End of exception handling block 00741 } while(0); 00742 00743 //Check whether the certificate is acceptable 00744 if(!error) 00745 { 00746 //Point to the structure that describes the certificate 00747 TlsCertDesc *cert = &context->certs[context->numCerts]; 00748 00749 //Save the certificate chain and the corresponding private key 00750 cert->certChain = certChain; 00751 cert->certChainLength = certChainLength; 00752 cert->privateKey = privateKey; 00753 cert->privateKeyLength = privateKeyLength; 00754 cert->type = certType; 00755 cert->signAlgo = certSignAlgo; 00756 cert->hashAlgo = certHashAlgo; 00757 cert->namedCurve = namedCurve; 00758 00759 //Update the number of certificates 00760 context->numCerts++; 00761 } 00762 00763 //Release previously allocated memory 00764 tlsFreeMem(derCert); 00765 tlsFreeMem(certInfo); 00766 00767 //Return status code 00768 return error; 00769 } 00770 00771 00772 /** 00773 * @brief Initiate the TLS handshake 00774 * @param[in] context Pointer to the TLS context 00775 * @return Error code 00776 **/ 00777 00778 error_t tlsConnect(TlsContext *context) 00779 { 00780 error_t error; 00781 00782 //Invalid TLS context? 00783 if(context == NULL) 00784 return ERROR_INVALID_PARAMETER; 00785 00786 //Ensure the I/O callback functions are properly registered 00787 if(context->sendCallback == NULL || context->receiveCallback == NULL) 00788 return ERROR_NOT_CONFIGURED; 00789 00790 //Verify that the PRNG is properly set 00791 if(context->prngAlgo == NULL || context->prngContext == NULL) 00792 return ERROR_NOT_CONFIGURED; 00793 00794 //Check current state 00795 if(context->state == TLS_STATE_INIT) 00796 { 00797 //Allocate send buffer if necessary 00798 if(context->txBuffer == NULL) 00799 { 00800 //Allocate TX buffer 00801 context->txBuffer = tlsAllocMem(context->txBufferSize); 00802 00803 //Failed to allocate memory? 00804 if(context->txBuffer == NULL) 00805 return ERROR_OUT_OF_MEMORY; 00806 00807 //Clear TX buffer 00808 memset(context->txBuffer, 0, context->txBufferSize); 00809 } 00810 00811 //Allocate receive buffer if necessary 00812 if(context->rxBuffer == NULL) 00813 { 00814 //Allocate RX buffer 00815 context->rxBuffer = tlsAllocMem(context->rxBufferSize); 00816 00817 //Failed to allocate memory? 00818 if(context->rxBuffer == NULL) 00819 { 00820 //Clean up side effects 00821 tlsFreeMem(context->txBuffer); 00822 context->txBuffer = NULL; 00823 //Report an error 00824 return ERROR_OUT_OF_MEMORY; 00825 } 00826 00827 //Clear RX buffer 00828 memset(context->rxBuffer, 0, context->rxBufferSize); 00829 } 00830 } 00831 00832 //Perform TLS handshake 00833 error = tlsHandshake(context); 00834 //Return status code 00835 return error; 00836 } 00837 00838 00839 /** 00840 * @brief Send application data to the remote host using TLS 00841 * @param[in] context Pointer to the TLS context 00842 * @param[in] data Pointer to a buffer containing the data to be transmitted 00843 * @param[in] length Number of bytes to be transmitted 00844 * @param[out] written Actual number of bytes written (optional parameter) 00845 * @param[in] flags Set of flags that influences the behavior of this function 00846 * @return Error code 00847 **/ 00848 00849 error_t tlsWrite(TlsContext *context, const void *data, 00850 size_t length, size_t *written, uint_t flags) 00851 { 00852 error_t error; 00853 size_t n; 00854 size_t totalLength; 00855 00856 //Invalid TLS context? 00857 if(context == NULL) 00858 return ERROR_INVALID_PARAMETER; 00859 00860 //Check parameters 00861 if(data == NULL && length != 0) 00862 return ERROR_INVALID_PARAMETER; 00863 00864 //Ensure the I/O callback functions are properly registered 00865 if(context->sendCallback == NULL || context->receiveCallback == NULL) 00866 return ERROR_NOT_CONFIGURED; 00867 00868 //Initialize status code 00869 error = NO_ERROR; 00870 00871 //Actual number of bytes written 00872 totalLength = 0; 00873 00874 //Send as much data as possible 00875 while(totalLength < length) 00876 { 00877 //Check current state 00878 if(context->state == TLS_STATE_APPLICATION_DATA) 00879 { 00880 //Calculate the number of bytes to write at a time 00881 n = MIN(length - totalLength, context->txRecordMaxLen); 00882 //The record length must not exceed 16384 bytes 00883 n = MIN(n, TLS_MAX_RECORD_LENGTH); 00884 00885 //Send application data 00886 error = tlsWriteProtocolData(context, data, n, TLS_TYPE_APPLICATION_DATA); 00887 00888 //Check status code 00889 if(!error) 00890 { 00891 //Advance data pointer 00892 data = (uint8_t *) data + n; 00893 //Update byte counter 00894 totalLength += n; 00895 } 00896 else 00897 { 00898 //Send an alert message to the peer, if applicable 00899 tlsProcessError(context, error); 00900 } 00901 } 00902 else 00903 { 00904 //The connection has not yet been established 00905 error = ERROR_NOT_CONNECTED; 00906 } 00907 00908 //Any error to report? 00909 if(error) 00910 break; 00911 } 00912 00913 //Total number of data that have been written 00914 if(written != NULL) 00915 *written = totalLength; 00916 00917 //Return status code 00918 return error; 00919 } 00920 00921 00922 /** 00923 * @brief Receive application data from a the remote host using TLS 00924 * @param[in] context Pointer to the TLS context 00925 * @param[out] data Buffer into which received data will be placed 00926 * @param[in] size Maximum number of bytes that can be received 00927 * @param[out] received Number of bytes that have been received 00928 * @param[in] flags Set of flags that influences the behavior of this function 00929 * @return Error code 00930 **/ 00931 00932 error_t tlsRead(TlsContext *context, void *data, 00933 size_t size, size_t *received, uint_t flags) 00934 { 00935 error_t error; 00936 size_t i; 00937 size_t n; 00938 uint8_t *p; 00939 TlsContentType contentType; 00940 00941 //Invalid TLS context? 00942 if(context == NULL) 00943 return ERROR_INVALID_PARAMETER; 00944 00945 //Check parameters 00946 if(data == NULL && received == NULL) 00947 return ERROR_INVALID_PARAMETER; 00948 00949 //Ensure the I/O callback functions are properly registered 00950 if(context->sendCallback == NULL || context->receiveCallback == NULL) 00951 return ERROR_NOT_CONFIGURED; 00952 00953 //Initialize status code 00954 error = NO_ERROR; 00955 00956 //No data has been read yet 00957 *received = 0; 00958 00959 //Read as much data as possible 00960 while(*received < size) 00961 { 00962 //Check current state 00963 if(context->state == TLS_STATE_APPLICATION_DATA) 00964 { 00965 //The TLS record layer receives uninterpreted data from higher layers 00966 error = tlsReadProtocolData(context, (void **) &p, &n, &contentType); 00967 00968 //Check status code 00969 if(!error) 00970 { 00971 //Application data received? 00972 if(contentType == TLS_TYPE_APPLICATION_DATA) 00973 { 00974 //Limit the number of bytes to read at a time 00975 n = MIN(n, size - *received); 00976 00977 //The TLS_FLAG_BREAK_CHAR flag causes the function to stop reading 00978 //data as soon as the specified break character is encountered 00979 if(flags & TLS_FLAG_BREAK_CHAR) 00980 { 00981 //Retrieve the break character code 00982 char_t c = LSB(flags); 00983 00984 //Search for the specified break character 00985 for(i = 0; i < n && p[i] != c; i++); 00986 //Adjust the number of data to read 00987 n = MIN(n, i + 1); 00988 00989 //Copy data to user buffer 00990 memcpy(data, p, n); 00991 //Total number of data that have been read 00992 *received += n; 00993 00994 //Advance data pointer 00995 context->rxBufferPos += n; 00996 //Number of bytes still pending in the receive buffer 00997 context->rxBufferLen -= n; 00998 00999 //Check whether a break character has been found 01000 if(n > 0 && p[n - 1] == c) 01001 break; 01002 } 01003 else 01004 { 01005 //Copy data to user buffer 01006 memcpy(data, p, n); 01007 //Total number of data that have been read 01008 *received += n; 01009 01010 //Advance data pointer 01011 context->rxBufferPos += n; 01012 //Number of bytes still pending in the receive buffer 01013 context->rxBufferLen -= n; 01014 01015 //The TLS_FLAG_WAIT_ALL flag causes the function to return 01016 //only when the requested number of bytes have been read 01017 if(!(flags & TLS_FLAG_WAIT_ALL)) 01018 break; 01019 } 01020 01021 //Advance data pointer 01022 data = (uint8_t *) data + n; 01023 } 01024 //Alert message received? 01025 else if(contentType == TLS_TYPE_ALERT) 01026 { 01027 //Parse Alert message 01028 error = tlsParseAlert(context, (TlsAlert *) p, n); 01029 01030 //Advance data pointer 01031 context->rxBufferPos += n; 01032 //Number of bytes still pending in the receive buffer 01033 context->rxBufferLen -= n; 01034 } 01035 //An inappropriate message was received? 01036 else 01037 { 01038 //Report an error 01039 error = ERROR_UNEXPECTED_MESSAGE; 01040 } 01041 } 01042 01043 //Any error to report? 01044 if(error) 01045 { 01046 //Send an alert message to the peer, if applicable 01047 tlsProcessError(context, error); 01048 } 01049 } 01050 else if(context->state == TLS_STATE_CLOSING || 01051 context->state == TLS_STATE_CLOSED) 01052 { 01053 //Check whether a fatal alert message has been sent or received 01054 if(context->fatalAlertSent || context->fatalAlertReceived) 01055 { 01056 //Alert messages with a level of fatal result in the immediate 01057 //termination of the connection 01058 error = ERROR_FAILURE; 01059 } 01060 else 01061 { 01062 //The user must be satisfied with data already on hand 01063 if(*received > 0) 01064 { 01065 //Some data are pending in the receive buffer 01066 error = NO_ERROR; 01067 break; 01068 } 01069 else 01070 { 01071 //The receive buffer is empty 01072 error = ERROR_END_OF_STREAM; 01073 } 01074 } 01075 } 01076 else 01077 { 01078 //The connection has not yet been established 01079 error = ERROR_NOT_CONNECTED; 01080 } 01081 01082 //Any error to report? 01083 if(error) 01084 break; 01085 } 01086 01087 //Return status code 01088 return error; 01089 } 01090 01091 01092 /** 01093 * @brief Gracefully close TLS session 01094 * @param[in] context Pointer to the TLS context 01095 **/ 01096 01097 error_t tlsShutdown(TlsContext *context) 01098 { 01099 //Either party may initiate a close by sending a close_notify alert 01100 return tlsShutdownEx(context, FALSE); 01101 } 01102 01103 01104 /** 01105 * @brief Gracefully close TLS session 01106 * @param[in] context Pointer to the TLS context 01107 * @param[in] waitForCloseNotify Wait for the close notify alert from the peer 01108 **/ 01109 01110 error_t tlsShutdownEx(TlsContext *context, bool_t waitForCloseNotify) 01111 { 01112 error_t error; 01113 size_t n; 01114 uint8_t *p; 01115 TlsContentType contentType; 01116 01117 //Invalid TLS context? 01118 if(context == NULL) 01119 return ERROR_INVALID_PARAMETER; 01120 01121 //Ensure the I/O callback functions are properly registered 01122 if(context->sendCallback == NULL || context->receiveCallback == NULL) 01123 return ERROR_NOT_CONFIGURED; 01124 01125 //Initialize status code 01126 error = NO_ERROR; 01127 01128 //Wait for the TLS session to be closed 01129 while(context->state != TLS_STATE_CLOSED) 01130 { 01131 //Check current state 01132 if(context->state == TLS_STATE_APPLICATION_DATA) 01133 { 01134 //Flush send buffer 01135 error = tlsWriteProtocolData(context, NULL, 0, TLS_TYPE_NONE); 01136 01137 //Check status code 01138 if(!error) 01139 { 01140 //Either party may initiate a close by sending a close_notify alert 01141 context->state = TLS_STATE_CLOSING; 01142 } 01143 } 01144 if(context->state == TLS_STATE_CLOSING) 01145 { 01146 //Flush send buffer 01147 error = tlsWriteProtocolData(context, NULL, 0, TLS_TYPE_NONE); 01148 01149 //Check status code 01150 if(!error) 01151 { 01152 //Unless some other fatal alert has been transmitted, each party 01153 //is required to send a close_notify alert before closing the 01154 //write side of the connection 01155 if(context->fatalAlertSent || context->fatalAlertReceived) 01156 { 01157 //Close the connection immediately 01158 context->state = TLS_STATE_CLOSED; 01159 } 01160 else if(!context->closeNotifySent) 01161 { 01162 //Notifies the recipient that the sender will not send any 01163 //more messages on this connection 01164 error = tlsSendAlert(context, TLS_ALERT_LEVEL_WARNING, 01165 TLS_ALERT_CLOSE_NOTIFY); 01166 } 01167 else if(!context->closeNotifyReceived && waitForCloseNotify) 01168 { 01169 //Wait for the responding close_notify alert 01170 error = tlsReadProtocolData(context, (void **) &p, &n, &contentType); 01171 01172 //Check status code 01173 if(!error) 01174 { 01175 //Application data received? 01176 if(contentType == TLS_TYPE_APPLICATION_DATA) 01177 { 01178 //Advance data pointer 01179 context->rxBufferPos += n; 01180 //Number of bytes still pending in the receive buffer 01181 context->rxBufferLen -= n; 01182 } 01183 //Alert message received? 01184 else if(contentType == TLS_TYPE_ALERT) 01185 { 01186 //Parse Alert message 01187 error = tlsParseAlert(context, (TlsAlert *) p, n); 01188 01189 //Advance data pointer 01190 context->rxBufferPos += n; 01191 //Number of bytes still pending in the receive buffer 01192 context->rxBufferLen -= n; 01193 } 01194 //An inappropriate message was received? 01195 else 01196 { 01197 //Report an error 01198 error = ERROR_UNEXPECTED_MESSAGE; 01199 } 01200 } 01201 } 01202 else 01203 { 01204 //The connection is closed 01205 context->state = TLS_STATE_CLOSED; 01206 } 01207 } 01208 } 01209 else 01210 { 01211 //Report an error 01212 error = ERROR_NOT_CONNECTED; 01213 } 01214 01215 //Any error to report? 01216 if(error) 01217 break; 01218 } 01219 01220 //Return status code 01221 return error; 01222 } 01223 01224 01225 /** 01226 * @brief Release TLS context 01227 * @param[in] context Pointer to the TLS context 01228 **/ 01229 01230 void tlsFree(TlsContext *context) 01231 { 01232 //Valid TLS context? 01233 if(context != NULL) 01234 { 01235 //Release server name 01236 if(context->serverName != NULL) 01237 tlsFreeMem(context->serverName); 01238 01239 #if (TLS_ALPN_SUPPORT == ENABLED) 01240 //Release the list of supported protocols 01241 if(context->protocolList != NULL) 01242 tlsFreeMem(context->protocolList); 01243 #endif 01244 01245 #if (TLS_PSK_SUPPORT == ENABLED || TLS_RSA_PSK_SUPPORT == ENABLED || \ 01246 TLS_DHE_PSK_SUPPORT == ENABLED || TLS_ECDHE_PSK_SUPPORT == ENABLED) 01247 //Release the pre-shared key 01248 if(context->psk != NULL) 01249 { 01250 memset(context->psk, 0, context->pskLen); 01251 tlsFreeMem(context->psk); 01252 } 01253 01254 //Release the PSK identity 01255 if(context->pskIdentity != NULL) 01256 tlsFreeMem(context->pskIdentity); 01257 01258 //Release the PSK identity hint 01259 if(context->pskIdentityHint != NULL) 01260 tlsFreeMem(context->pskIdentityHint); 01261 #endif 01262 01263 #if (TLS_DH_ANON_SUPPORT == ENABLED || TLS_DHE_RSA_SUPPORT == ENABLED || \ 01264 TLS_DHE_DSS_SUPPORT == ENABLED || TLS_DHE_PSK_SUPPORT == ENABLED) 01265 //Release Diffie-Hellman context 01266 dhFree(&context->dhContext); 01267 #endif 01268 01269 #if (TLS_ECDH_ANON_SUPPORT == ENABLED || TLS_ECDHE_RSA_SUPPORT == ENABLED || \ 01270 TLS_ECDHE_ECDSA_SUPPORT == ENABLED || TLS_ECDHE_PSK_SUPPORT == ENABLED) 01271 //Release ECDH context 01272 ecdhFree(&context->ecdhContext); 01273 #endif 01274 01275 #if (TLS_RSA_SIGN_SUPPORT == ENABLED || TLS_RSA_SUPPORT == ENABLED || \ 01276 TLS_DHE_RSA_SUPPORT == ENABLED || TLS_ECDHE_RSA_SUPPORT == ENABLED) 01277 //Release peer's RSA public key 01278 rsaFreePublicKey(&context->peerRsaPublicKey); 01279 #endif 01280 01281 #if (TLS_DSA_SIGN_SUPPORT == ENABLED || TLS_DHE_DSS_SUPPORT == ENABLED) 01282 //Release peer's DSA public key 01283 dsaFreePublicKey(&context->peerDsaPublicKey); 01284 #endif 01285 01286 #if (TLS_ECDSA_SIGN_SUPPORT == ENABLED || TLS_ECDHE_ECDSA_SUPPORT == ENABLED) 01287 //Release peer's EC domain parameters 01288 ecFreeDomainParameters(&context->peerEcParams); 01289 //Release peer's EC public key 01290 ecFree(&context->peerEcPublicKey); 01291 #endif 01292 01293 //Release send buffer 01294 if(context->txBuffer != NULL) 01295 { 01296 memset(context->txBuffer, 0, context->txBufferSize); 01297 tlsFreeMem(context->txBuffer); 01298 } 01299 01300 //Release receive buffer 01301 if(context->rxBuffer != NULL) 01302 { 01303 memset(context->rxBuffer, 0, context->rxBufferSize); 01304 tlsFreeMem(context->rxBuffer); 01305 } 01306 01307 //Release the MD5 context used to compute verify data 01308 if(context->handshakeMd5Context != NULL) 01309 { 01310 memset(context->handshakeMd5Context, 0, sizeof(Md5Context)); 01311 tlsFreeMem(context->handshakeMd5Context); 01312 } 01313 01314 //Release the SHA-1 context used to compute verify data 01315 if(context->handshakeSha1Context != NULL) 01316 { 01317 memset(context->handshakeSha1Context, 0, sizeof(Sha1Context)); 01318 tlsFreeMem(context->handshakeSha1Context); 01319 } 01320 01321 //Release the hash context used to compute verify data (TLS 1.2) 01322 if(context->handshakeHashContext != NULL) 01323 { 01324 memset(context->handshakeHashContext, 0, context->prfHashAlgo->contextSize); 01325 tlsFreeMem(context->handshakeHashContext); 01326 } 01327 01328 //Release the encryption context (TX path) 01329 if(context->writeCipherContext != NULL) 01330 { 01331 memset(context->writeCipherContext, 0, context->cipherAlgo->contextSize); 01332 tlsFreeMem(context->writeCipherContext); 01333 } 01334 01335 //Release the encryption context (RX path) 01336 if(context->readCipherContext != NULL) 01337 { 01338 memset(context->readCipherContext, 0, context->cipherAlgo->contextSize); 01339 tlsFreeMem(context->readCipherContext); 01340 } 01341 01342 #if (TLS_GCM_CIPHER_SUPPORT == ENABLED) 01343 //Release the GCM context (TX path) 01344 if(context->writeGcmContext != NULL) 01345 { 01346 memset(context->writeGcmContext, 0, sizeof(GcmContext)); 01347 tlsFreeMem(context->writeGcmContext); 01348 } 01349 01350 //Release the GCM context (RX path) 01351 if(context->readGcmContext != NULL) 01352 { 01353 memset(context->readGcmContext, 0, sizeof(GcmContext)); 01354 tlsFreeMem(context->readGcmContext); 01355 } 01356 #endif 01357 01358 //Clear the TLS context before freeing memory 01359 memset(context, 0, sizeof(TlsContext)); 01360 tlsFreeMem(context); 01361 } 01362 } 01363 01364 01365 /** 01366 * @brief Save TLS session 01367 * @param[in] context Pointer to the TLS context 01368 * @param[out] session Buffer where to store the current session parameters 01369 * @return Error code 01370 **/ 01371 01372 error_t tlsSaveSession(const TlsContext *context, TlsSession *session) 01373 { 01374 //Check parameters 01375 if(context == NULL || session == NULL) 01376 return ERROR_INVALID_PARAMETER; 01377 01378 //Invalid session parameters? 01379 if(!context->sessionIdLen || !context->cipherSuite) 01380 return ERROR_FAILURE; 01381 01382 //Save session identifier 01383 memcpy(session->id, context->sessionId, context->sessionIdLen); 01384 session->idLength = context->sessionIdLen; 01385 01386 //Get current time 01387 session->timestamp = osGetSystemTime(); 01388 01389 //Negotiated cipher suite and compression method 01390 session->cipherSuite = context->cipherSuite; 01391 session->compressionMethod = context->compressionMethod; 01392 01393 //Save master secret 01394 memcpy(session->masterSecret, context->masterSecret, 48); 01395 01396 //Successful processing 01397 return NO_ERROR; 01398 } 01399 01400 01401 /** 01402 * @brief Restore TLS session 01403 * @param[in] context Pointer to the TLS context 01404 * @param[in] session Pointer to the session to be restored 01405 * @return Error code 01406 **/ 01407 01408 error_t tlsRestoreSession(TlsContext *context, const TlsSession *session) 01409 { 01410 //Check parameters 01411 if(context == NULL || session == NULL) 01412 return ERROR_INVALID_PARAMETER; 01413 01414 //Restore session identifier 01415 memcpy(context->sessionId, session->id, session->idLength); 01416 context->sessionIdLen = session->idLength; 01417 01418 //Negotiated cipher suite and compression method 01419 context->cipherSuite = session->cipherSuite; 01420 context->compressionMethod = session->compressionMethod; 01421 01422 //Restore master secret 01423 memcpy(context->masterSecret, session->masterSecret, 48); 01424 01425 //Successful processing 01426 return NO_ERROR; 01427 } 01428 01429 #endif 01430
Generated on Tue Jul 12 2022 17:10:17 by
