/* internal.c * * Copyright (C) 2006-2026 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 3 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 */ #include /* * internal.c Build Options: * * See also: tls.c for TLS extension/protocol options, tls13.c for TLS 1.3, * ssl.c for SSL API layer, wc_port.c for platform/memory. * * Connection & Buffers: * LARGE_STATIC_BUFFERS: Use large static I/O buffers default: on * WOLFSSL_DISABLE_EARLY_SANITY_CHECKS: * Disable early sanity checks on TLS messages default: off * WOLFSSL_NO_DTLS_SIZE_CHECK: Disable DTLS record size validation default: off * * Cipher Suite Selection: * NO_CHAPOL_AEAD: Disable ChaCha20-Poly1305 AEAD suites default: off * WOLFSSL_OLDTLS_AEAD_CIPHERSUITES: * Enable AEAD cipher suites for pre-TLS 1.2 default: off * WOLFSSL_OLDTLS_SHA2_CIPHERSUITES: * Enable SHA-2 cipher suites for pre-TLS 1.2 default: off * WOLFSSL_NO_STRICT_CIPHER_SUITE: * Relax strict cipher suite validation default: off * NO_RESUME_SUITE_CHECK: Skip cipher suite check on resume default: off * NO_FORCE_SCR_SAME_SUITE: Allow different suite in renegotiation default: off * CIPHER_NONCE: Per-record cipher nonce for AEAD default: off * * Certificate Validation: * WOLFSSL_SMALL_CERT_VERIFY: Verify cert sig without DecodedCert default: off * WOLFSSL_ALT_CERT_CHAINS: Allow non-validated intermediate CAs default: off * NO_CHECK_PRIVATE_KEY: Skip key/cert matching validation default: off * WOLFSSL_VERIFY_CB_ALL_CERTS: * Call verify callback for all chain certs default: off * WOLFSSL_ALWAYS_VERIFY_CB: Always invoke verify callback default: off * WOLFSSL_ALLOW_NO_CN_IN_SAN: Allow certs with SAN but no CN default: off * WOLFSSL_TRUST_PEER_CERT: Direct trust of specific peer certs default: off * WOLFSSL_LOCAL_X509_STORE: Per-context X509 store default: off * WOLFSSL_APPLE_NATIVE_CERT_VALIDATION: * Use Apple native cert validation on macOS/iOS default: off * WOLFSSL_TEST_APPLE_NATIVE_CERT_VALIDATION: * Testing mode for Apple cert validation default: off * HAVE_DANE: DNS-based cert validation (DNSSEC) default: off * HAVE_FALLBACK_SCSV: TLS Fallback SCSV anti-downgrade default: off * WOLFSSL_ACERT: Attribute certificate support default: off * WOLFSSL_DEBUG_CERTS: Debug logging for cert processing default: off * WOLFSSL_HOSTNAME_VERIFY_ALT_NAME_ONLY: * Verify hostname using SAN only (not CN) default: off * * Handshake Behavior: * OLD_HELLO_ALLOWED: Allow SSLv2-format ClientHello default: off * WOLFSSL_ALTERNATIVE_DOWNGRADE: * Alternative protocol downgrade detection default: off * WOLFSSL_OLD_TIMINGPADVERIFY: * Old timing-based CBC padding verification default: off * WOLFSSL_ECDSA_MATCH_HASH: Match ECDSA hash to curve preference default: off * WOLFSSL_STRONGEST_HASH_SIG: Prefer strongest hash in signatures default: off * USE_ECDSA_KEYSZ_HASH_ALGO: Select ECDSA hash by key size default: off * WOLFSSL_ALLOW_TLS_SHA1: Allow SHA-1 cipher suites/signatures default: off * WOLFSSL_EXTRA_ALERTS: Send additional TLS alert messages default: off * WOLFSSL_NO_ETM_ALERT: No alert on Encrypt-Then-MAC failure default: off * * Secure Renegotiation & PSK: * WOLFSSL_SECURE_RENEGOTIATION_ON_BY_DEFAULT: * Enable secure renegotiation by default default: off * WOLFSSL_PSK_IDENTITY_ALERT: Alert on PSK identity lookup failure default: off * * Session Tickets: * WOLFSSL_NO_DEF_TICKET_ENC_CB: * No default ticket encryption callback default: off * WOLFSSL_TICKET_ENC_CHACHA20_POLY1305: * ChaCha20-Poly1305 for ticket encryption default: auto * WOLFSSL_TICKET_ENC_AES128_GCM: * AES128-GCM for ticket encryption default: auto * WOLFSSL_TICKET_ENC_AES256_GCM: * AES256-GCM for ticket encryption default: off * WOLFSSL_TICKET_DECRYPT_NO_CREATE: * No new ticket on successful decryption default: off * WOLFSSL_TICKET_ENC_CBC_HMAC: * CBC+HMAC for ticket encryption (non-AEAD) default: off * WOLFSSL_NO_TICKET_EXPIRE: Disable ticket expiration checking default: off * * TLS 1.3 Internals: * WOLFSSL_TLS13_IGNORE_PT_ALERT_ON_ENC: * Ignore plaintext alerts when encrypted expected default: off * WOLFSSL_TLS13_NO_PEEK_HANDSHAKE_DONE: * Disable peek returning WANT_READ for tickets default: off * WOLFSSL_TLS13_IGNORE_AEAD_LIMITS: * Ignore AEAD message limits from RFC 8446 default: off * WOLFSSL_DTLS13_SEND_MOREACK_DEFAULT: * Send more ACKs by default in DTLS 1.3 default: off * * DTLS: * WOLFSSL_DTLS_RESEND_ONLY_TIMEOUT: * Resend previous flight only on timeout default: off * WOLFSSL_DTLS_DISALLOW_FUTURE: * Reject DTLS records with future epoch default: off * WOLFSSL_DTLS_RECORDS_CAN_SPAN_DATAGRAMS: * Allow DTLS records to span datagrams default: off * WOLFSSL_DEBUG_DTLS: Debug logging for DTLS operations default: off * * Session Export: * WOLFSSL_SESSION_EXPORT: Enable session export/import default: off * WOLFSSL_SESSION_EXPORT_DEBUG: * Debug logging for session export/import default: off * WOLFSSL_SESSION_EXPORT_NOPEER: * Export sessions without peer cert info default: off * * Compatibility Layers: * WOLFSSL_MYSQL_COMPATIBLE: MySQL protocol compatibility default: off * WOLFSSL_OPENVPN: OpenVPN compatibility behaviors default: off * * Async & Non-blocking: * WOLFSSL_ASYNC_CRYPT_SW: Software async crypto simulation default: off * WC_X25519_NONBLOCK: Non-blocking X25519 operations default: off * HAVE_WOLF_EVENT: Event-driven async processing default: off * * Hardware/Platform TLS: * WOLFSSL_MAXQ10XX_TLS: Maxim MAXQ10xx secure element default: off * WOLFSSL_IOTSAFE: IoTSAFE (GSMA) applet support default: off * WOLFSSL_QNX_CAAM: QNX CAAM crypto module support default: off * HAVE_DH_DEFAULT_PARAMS: Include default DH parameters default: off * HAVE_EXT_CACHE: External session cache callbacks default: off * * Hardening: * WOLFSSL_HARDEN_TLS: Implement RFC 9325 recommendations default: off * WOLFSSL_HARDEN_TLS_ALLOW_TRUNCATED_HMAC: Allow truncated HMAC * WOLFSSL_HARDEN_TLS_ALLOW_OLD_TLS: Allow old TLS versions * WOLFSSL_HARDEN_TLS_NO_SCR_CHECK: No SCR check * WOLFSSL_HARDEN_TLS_NO_PKEY_CHECK: No public key check * WOLFSSL_HARDEN_TLS_ALLOW_ALL_CIPHERSUITES: Allow all suites * WOLFSSL_NO_INIT_CTX_KEY: Allow SSL objects without loaded keys default: off */ #ifndef WOLFCRYPT_ONLY #include #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 #ifdef HAVE_ARIA /* included to get ARIA 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 = (int)(err); goto eLabel; } #define CHECK_RET(ret, exp, eLabel) do { if (((ret) = (exp)) != 0) goto eLabel;\ } while(0) #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 #if !defined(NO_TLS) && !defined(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 /* !NO_WOLFSSL_CLIENT */ #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 #endif /* !NO_WOLFSSL_SERVER */ #endif /* !NO_TLS && !WOLFSSL_NO_TLS12 */ #if !defined(NO_WOLFSSL_SERVER) && defined(HAVE_SESSION_TICKET) #if defined(WOLFSSL_HAPROXY) #define SSL_TICKET_CTX(ssl) ssl->initial_ctx->ticketEncCtx #else #define SSL_TICKET_CTX(ssl) ssl->ctx->ticketEncCtx #endif #if !defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) && !defined(NO_TLS) 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 /* !NO_WOLFSSL_SERVER && HAVE_SESSION_TICKET */ int writeAeadAuthData(WOLFSSL* ssl, word16 sz, byte type, byte* additional, byte dec, byte** seq, int verifyOrder); #ifdef WOLFSSL_DTLS static int _DtlsCheckWindow(WOLFSSL* ssl); #endif #if defined(__APPLE__) && defined(WOLFSSL_SYS_CA_CERTS) && \ (!defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH)) #include #include #include static int DoAppleNativeCertValidation(WOLFSSL* ssl, const WOLFSSL_BUFFER_INFO* certs, int totalCerts); #endif /* #if defined(__APPLE__) && defined(WOLFSSL_SYS_CA_CERTS) */ #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 }; #if !defined(NO_TLS) && !defined(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 /* !NO_TLS && !WOLFSSL_NO_TLS12 */ #if !defined(NO_CERT) && defined(WOLFSSL_BLIND_PRIVATE_KEY) int wolfssl_priv_der_blind(WC_RNG* rng, DerBuffer* key, DerBuffer** mask) { int ret = 0; WC_RNG local_rng; if (key != NULL) { if (*mask != NULL) { FreeDer(mask); } ret = AllocDer(mask, key->length, key->type, key->heap); if ((ret == 0) && (rng == NULL)) { if (wc_InitRng(&local_rng) != 0) { ret = RNG_FAILURE_E; } else { rng = &local_rng; } } if (ret == 0) { ret = wc_RNG_GenerateBlock(rng, (*mask)->buffer, (*mask)->length); } if (ret == 0) { xorbuf(key->buffer, (*mask)->buffer, (*mask)->length); } if (rng == &local_rng) { wc_FreeRng(rng); } } return ret; } void wolfssl_priv_der_blind_toggle(DerBuffer* key, const DerBuffer* mask) { if ((key != NULL) && (mask != NULL)) { xorbuf(key->buffer, mask->buffer, mask->length); } } DerBuffer *wolfssl_priv_der_unblind(const DerBuffer* key, const DerBuffer* mask) { DerBuffer *ret; if ((key == NULL) || (mask == NULL)) return NULL; if (mask->length > key->length) return NULL; if (AllocDer(&ret, key->length, key->type, key->heap) != 0) return NULL; xorbufout(ret->buffer, key->buffer, mask->buffer, mask->length); return ret; } void wolfssl_priv_der_unblind_free(DerBuffer* key) { if (key != NULL) FreeDer(&key); } #endif /* !NO_CERT && WOLFSSL_BLIND_PRIVATE_KEY */ #if defined(WOLFSSL_RENESAS_FSPSM_TLS) || 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 /* * This function builds up string for key-logging then call user's * key-log-callback to pass the string. * The user's key-logging callback has been set via * wolfSSL_CTX_set_keylog_callback function. The logging string format is: * "