/* internal.c * * Copyright (C) 2006-2022 wolfSSL Inc. * * This file is part of wolfSSL. * * wolfSSL is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * wolfSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ #ifdef HAVE_CONFIG_H #include #endif #include /* * WOLFSSL_SMALL_CERT_VERIFY: * Verify the certificate signature without using DecodedCert. Doubles up * on some code but allows smaller peak heap memory usage. * Cannot be used with WOLFSSL_NONBLOCK_OCSP. * WOLFSSL_ALT_CERT_CHAINS: * Allows CA's to be presented by peer, but not part of a valid chain. * Default wolfSSL behavior is to require validation of all presented peer * certificates. This also allows loading intermediate CA's as trusted * and ignoring no signer failures for CA's up the chain to root. * WOLFSSL_DTLS_RESEND_ONLY_TIMEOUT: * Enable resending the previous DTLS handshake flight only on a network * read timeout. By default we resend in two more cases, when we receive: * - an out of order last msg of the peer's flight * - a duplicate of the first msg from the peer's flight * WOLFSSL_NO_DEF_TICKET_ENC_CB: * No default ticket encryption callback. * Server only. * Application must set its own callback to use session tickets. * WOLFSSL_TICKET_ENC_CHACHA20_POLY1305 * Use ChaCha20-Poly1305 to encrypt/decrypt session tickets in default * callback. Default algorithm if none defined and algorithms compiled in. * Server only. * WOLFSSL_TICKET_ENC_AES128_GCM * Use AES128-GCM to encrypt/decrypt session tickets in default callback. * Server only. Default algorithm if ChaCha20/Poly1305 not compiled in. * WOLFSSL_TICKET_ENC_AES256_GCM * Use AES256-GCM to encrypt/decrypt session tickets in default callback. * Server only. * WOLFSSL_TICKET_DECRYPT_NO_CREATE * Default callback will not request creation of new ticket on successful * decryption. * Server only. * WOLFSSL_TLS13_NO_PEEK_HANDSHAKE_DONE * Once a normal TLS 1.3 handshake is complete, a session ticket message * may be received by a client. To support detecting this, peek will * return WOLFSSL_ERROR_WANT_READ. * This define turns off this behaviour. * WOLFSSL_DTLS_NO_HVR_ON_RESUME * If defined, a DTLS server will not do a cookie exchange on successful * client resumption: the resumption will be faster (one RTT less) and * will consume less bandwidth (one ClientHello and one HelloVerifyRequest * less). On the other hand, if a valid SessionID is collected, forged * clientHello messages will consume resources on the server. * This define is turned off by default. * WOLFSSL_HOSTNAME_VERIFY_ALT_NAME_ONLY * Verify hostname/ip address using alternate name (SAN) only and do not * use the common name. Forces use of the alternate name, so certificates * missing SAN will be rejected during the handshake * WOLFSSL_CHECK_SIG_FAULTS * Verifies the ECC signature after signing in case of faults in the * calculation of the signature. Useful when signature fault injection is a * possible attack. * WOLFSSL_TLS13_IGNORE_AEAD_LIMITS * Ignore the AEAD limits for messages specified in the RFC. After * reaching the limit, we initiate a key update. We enforce the AEAD limits * by default. * https://www.rfc-editor.org/rfc/rfc8446#section-5.5 * https://www.rfc-editor.org/rfc/rfc9147.html#name-aead-limits */ #ifdef EXTERNAL_OPTS_OPENVPN #error EXTERNAL_OPTS_OPENVPN should not be defined\ when building wolfSSL #endif #ifndef WOLFCRYPT_ONLY #include #include #include #include #ifdef NO_INLINE #include #else #define WOLFSSL_MISC_INCLUDED #include #endif #if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) && !defined(NO_SHA) #include #endif #if defined(OPENSSL_EXTRA) && defined(HAVE_SECRET_CALLBACK) #include #endif #ifdef HAVE_LIBZ #include "zlib.h" #endif #ifdef WOLFSSL_QNX_CAAM /* included to get CAAM devId value */ #include #endif #if defined(DEBUG_WOLFSSL) || defined(SHOW_SECRETS) || \ defined(CHACHA_AEAD_TEST) || defined(WOLFSSL_SESSION_EXPORT_DEBUG) #ifndef NO_STDIO_FILESYSTEM #ifdef FUSION_RTOS #include #else #include #endif #endif #endif #ifdef __sun #include #endif #define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; } #ifdef _MSC_VER /* disable for while(0) cases at the .c level for now */ #pragma warning(disable:4127) #endif #if defined(WOLFSSL_CALLBACKS) && !defined(LARGE_STATIC_BUFFERS) #error \ WOLFSSL_CALLBACKS needs LARGE_STATIC_BUFFERS, please add LARGE_STATIC_BUFFERS #endif #if defined(HAVE_SECURE_RENEGOTIATION) && defined(HAVE_RENEGOTIATION_INDICATION) #error Cannot use both secure-renegotiation and renegotiation-indication #endif #ifndef WOLFSSL_NO_TLS12 #ifndef NO_WOLFSSL_CLIENT static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size); #ifndef NO_CERTS static int DoCertificateRequest(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size); #endif #ifdef HAVE_SESSION_TICKET static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size); #endif #endif #ifndef NO_WOLFSSL_SERVER static int DoClientKeyExchange(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 size); #if (!defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \ defined(HAVE_ED448)) && !defined(WOLFSSL_NO_CLIENT_AUTH) static int DoCertificateVerify(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 size); #endif #ifdef WOLFSSL_DTLS static int SendHelloVerifyRequest(WOLFSSL* ssl, const byte* cookie, byte cookieSz); #endif /* WOLFSSL_DTLS */ #endif /* !NO_WOLFSSL_SERVER */ #endif /* !WOLFSSL_NO_TLS12 */ #ifndef NO_WOLFSSL_SERVER #if defined(HAVE_SESSION_TICKET) && !defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) static int TicketEncCbCtx_Init(WOLFSSL_CTX* ctx, TicketEncCbCtx* keyCtx); static void TicketEncCbCtx_Free(TicketEncCbCtx* keyCtx); static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ], byte iv[WOLFSSL_TICKET_IV_SZ], byte mac[WOLFSSL_TICKET_MAC_SZ], int enc, byte* ticket, int inLen, int* outLen, void* userCtx); #endif #endif #ifdef WOLFSSL_DTLS static int _DtlsCheckWindow(WOLFSSL* ssl); static int _DtlsUpdateWindow(WOLFSSL* ssl); #endif #ifdef WOLFSSL_DTLS13 #ifndef WOLFSSL_DTLS13_SEND_MOREACK_DEFAULT #define WOLFSSL_DTLS13_SEND_MOREACK_DEFAULT 0 #endif #endif /* WOLFSSL_DTLS13 */ enum processReply { doProcessInit = 0, #ifndef NO_WOLFSSL_SERVER runProcessOldClientHello, #endif getRecordLayerHeader, getData, verifyEncryptedMessage, decryptMessage, verifyMessage, runProcessingOneRecord, runProcessingOneMessage }; #ifndef WOLFSSL_NO_TLS12 #if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT) /* Server random bytes for TLS v1.3 described downgrade protection mechanism. */ static const byte tls13Downgrade[7] = { 0x44, 0x4f, 0x57, 0x4e, 0x47, 0x52, 0x44 }; #define TLS13_DOWNGRADE_SZ sizeof(tls13Downgrade) #endif /* !NO_WOLFSSL_SERVER || !NO_WOLFSSL_CLIENT */ #if !defined(NO_OLD_TLS) && !defined(WOLFSSL_AEAD_ONLY) static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, int padLen, int content, int verify, int epochOrder); #endif #endif /* !WOLFSSL_NO_TLS12 */ #if defined(WOLFSSL_RENESAS_SCEPROTECT) || defined(WOLFSSL_RENESAS_TSIP_TLS) #include #endif #if defined(OPENSSL_EXTRA) && defined(HAVE_SECRET_CALLBACK) static int SessionSecret_callback(WOLFSSL* ssl, void* secret, int* secretSz, void* ctx); #ifdef WOLFSSL_TLS13 static int SessionSecret_callback_Tls13(WOLFSSL* ssl, int id, const unsigned char* secret, int secretSz, void* ctx); #endif /* Label string for client random. */ #define SSC_CR "CLIENT_RANDOM" /* * This function builds up string for key-logging then call user's * key-log-callback to pass the string for TLS1.2 and older. * The user's key-logging callback has been set via * wolfSSL_CTX_set_keylog_callback function. The logging string format is: * "CLIENT_RANDOM " * parameter * - ssl: WOLFSSL object * - secret: pointer to the buffer holding master-secret * - secretSz: size of secret * - ctx: not used * returns 0 on success, negative value on failure. */ static int SessionSecret_callback(WOLFSSL* ssl, void* secret, int* secretSz, void* ctx) { wolfSSL_CTX_keylog_cb_func logCb = NULL; int msSz; int hasVal; int i; const char* label = SSC_CR; int labelSz = sizeof(SSC_CR); int buffSz; byte* log = NULL; word32 outSz; int idx; int ret; (void)ctx; if (ssl == NULL || secret == NULL || *secretSz == 0) return BAD_FUNC_ARG; if (ssl->arrays == NULL) return BAD_FUNC_ARG; /* get the user-callback func from CTX*/ logCb = ssl->ctx->keyLogCb; if (logCb == NULL) return 0; /* need to make sure the given master-secret has a meaningful value */ msSz = *secretSz; hasVal = 0; for (i = 0; i < msSz; i++) { if (*((byte*)secret) != 0) { hasVal = 1; break; } } if (hasVal == 0) return 0; /* master-secret looks invalid */ /* build up a hex-decoded keylog string "CLIENT_RANDOM " note that each keylog string does not have CR/LF. */ buffSz = labelSz + (RAN_LEN * 2) + 1 + ((*secretSz) * 2) + 1; log = XMALLOC(buffSz, ssl->heap, DYNAMIC_TYPE_SECRET); if (log == NULL) return MEMORY_E; #ifdef WOLFSSL_CHECK_MEM_ZERO wc_MemZero_Add("SessionSecret log", log, buffSz); #endif XMEMSET(log, 0, buffSz); XMEMCPY(log, label, labelSz -1); /* put label w/o terminator */ log[labelSz - 1] = ' '; /* '\0' -> ' ' */ idx = labelSz; outSz = buffSz - idx; if ((ret = Base16_Encode(ssl->arrays->clientRandom, RAN_LEN, log + idx, &outSz)) == 0) { idx += (outSz - 1); /* reduce terminator byte */ outSz = buffSz - idx; if (outSz > 1) { log[idx++] = ' '; /* add space*/ outSz = buffSz - idx; if ((ret = Base16_Encode((byte*)secret, *secretSz, log + idx, &outSz)) == 0) { /* pass the log to the client callback*/ logCb(ssl, (char*)log); ret = 0; } } else ret = MEMORY_E; } /* Zero out Base16 encoded secret and other data. */ ForceZero(log, buffSz); XFREE(log, ssl->heap, DYNAMIC_TYPE_SECRET); return ret; } #if defined(WOLFSSL_TLS13) /* Label string for client early traffic secret. */ #define SSC_TLS13_CETS "CLIENT_EARLY_TRAFFIC_SECRET" /* Label string for client handshake traffic secret. */ #define SSC_TLS13_CHTS "CLIENT_HANDSHAKE_TRAFFIC_SECRET" /* Label string for server handshake traffic secret. */ #define SSC_TLS13_SHTS "SERVER_HANDSHAKE_TRAFFIC_SECRET" /* Label string for client traffic secret. */ #define SSC_TLS13_CTS "CLIENT_TRAFFIC_SECRET_0" /* Label string for server traffic secret. */ #define SSC_TLS13_STS "SERVER_TRAFFIC_SECRET_0" /* Label string for early exporter secret. */ #define SSC_TLS13_EES "EARLY_EXPORTER_SECRET" /* Label string for exporter secret. */ #define SSC_TLS13_ES "EXPORTER_SECRET" /* * This function builds up string for key-logging then call user's * key-log-callback to pass the string for TLS1.3. * The user's key-logging callback has been set via * wolfSSL_CTX_set_keylog_callback function. The logging string format is: * "