@@ -25,10 +25,16 @@ #include "tlsInt.h" #include "tclOpts.h" #include #include #include +#include + +/* Min OpenSSL version */ +#if OPENSSL_VERSION_NUMBER < 0x10101000L +#error "Only OpenSSL v1.1.1 or later is supported" +#endif /* * External functions */ @@ -64,29 +70,10 @@ #ifndef OPENSSL_NO_DH #include "dh_params.h" #endif -/* - * We lose the tcl password callback when we use the RSA BSAFE SSL-C 1.1.2 - * libraries instead of the current OpenSSL libraries. - */ - -#ifdef BSAFE -#define PRE_OPENSSL_0_9_4 1 -#endif - -/* - * Pre OpenSSL 0.9.4 Compat - */ - -#ifndef STACK_OF -#define STACK_OF(x) STACK -#define sk_SSL_CIPHER_num(sk) sk_num((sk)) -#define sk_SSL_CIPHER_value(sk, index) (SSL_CIPHER*)sk_value((sk), (index)) -#endif - /* * Thread-Safe TLS Code */ #ifdef TCL_THREADS @@ -93,11 +80,10 @@ #define OPENSSL_THREAD_DEFINES #include #ifdef OPENSSL_THREADS #include -/* Added */ #include /* * Threaded operation requires locking callbacks * Based from /crypto/cryptlib.c of OpenSSL and NSOpenSSL. @@ -104,44 +90,10 @@ */ static Tcl_Mutex *locks = NULL; static int locksCount = 0; static Tcl_Mutex init_mx; - -# if OPENSSL_VERSION_NUMBER < 0x10100000L - -void CryptoThreadLockCallback(int mode, int n, const char *file, int line) { - - if (mode & CRYPTO_LOCK) { - /* This debugging is turned off by default -- it's too noisy. */ - /* dprintf("Called to lock (n=%i of %i)", n, locksCount); */ - Tcl_MutexLock(&locks[n]); - } else { - /* dprintf("Called to unlock (n=%i of %i)", n, locksCount); */ - Tcl_MutexUnlock(&locks[n]); - } - - /* dprintf("Returning"); */ - - return; - file = file; - line = line; -} - -unsigned long CryptoThreadIdCallback(void) { - unsigned long ret; - - dprintf("Called"); - - ret = (unsigned long) Tcl_GetCurrentThread(); - - dprintf("Returning %lu", ret); - - return(ret); -} - -#endif #endif /* OPENSSL_THREADS */ #endif /* TCL_THREADS */ /* @@ -409,23 +361,10 @@ * Called when a password is needed to unpack RSA and PEM keys. * Evals any bound password script and returns the result as * the password string. *------------------------------------------------------------------- */ -#ifdef PRE_OPENSSL_0_9_4 -/* - * No way to handle user-data therefore no way without a global - * variable to access the Tcl interpreter. -*/ -static int -PasswordCallback(char *buf, int size, int verify) { - return -1; - buf = buf; - size = size; - verify = verify; -} -#else static int PasswordCallback(char *buf, int size, int verify, void *udata) { State *statePtr = (State *) udata; Tcl_Interp *interp = statePtr->interp; Tcl_Obj *cmdPtr; @@ -471,11 +410,10 @@ } Tcl_Release((ClientData) interp); return -1; verify = verify; } -#endif /* *------------------------------------------------------------------- * * CiphersObjCmd -- list available ciphers @@ -530,32 +468,32 @@ return TCL_ERROR; #else ctx = SSL_CTX_new(SSLv2_method()); break; #endif case TLS_SSL3: -#if defined(NO_SSL3) || defined(OPENSSL_NO_SSL3) +#if defined(NO_SSL3) || defined(OPENSSL_NO_SSL3) || defined(OPENSSL_NO_SSL3_METHOD) Tcl_AppendResult(interp, protocols[index], ": protocol not supported", NULL); return TCL_ERROR; #else ctx = SSL_CTX_new(SSLv3_method()); break; #endif case TLS_TLS1: -#if defined(NO_TLS1) || defined(OPENSSL_NO_TLS1) +#if defined(NO_TLS1) || defined(OPENSSL_NO_TLS1) || defined(OPENSSL_NO_TLS1_METHOD) Tcl_AppendResult(interp, protocols[index], ": protocol not supported", NULL); return TCL_ERROR; #else ctx = SSL_CTX_new(TLSv1_method()); break; #endif case TLS_TLS1_1: -#if defined(NO_TLS1_1) || defined(OPENSSL_NO_TLS1_1) +#if defined(NO_TLS1_1) || defined(OPENSSL_NO_TLS1_1) || defined(OPENSSL_NO_TLS1_1_METHOD) Tcl_AppendResult(interp, protocols[index], ": protocol not supported", NULL); return TCL_ERROR; #else ctx = SSL_CTX_new(TLSv1_1_method()); break; #endif case TLS_TLS1_2: -#if defined(NO_TLS1_2) || defined(OPENSSL_NO_TLS1_2) +#if defined(NO_TLS1_2) || defined(OPENSSL_NO_TLS1_2) || defined(OPENSSL_NO_TLS1_2_METHOD) Tcl_AppendResult(interp, protocols[index], ": protocol not supported", NULL); return TCL_ERROR; #else ctx = SSL_CTX_new(TLSv1_2_method()); break; #endif @@ -798,25 +736,23 @@ char *ciphersuites = NULL; char *CAfile = NULL; char *CAdir = NULL; char *DHparams = NULL; char *model = NULL; -#ifndef OPENSSL_NO_TLSEXT char *servername = NULL; /* hostname for Server Name Indication */ Tcl_Obj *alpn = NULL; -#endif int ssl2 = 0, ssl3 = 0; int tls1 = 1, tls1_1 = 1, tls1_2 = 1, tls1_3 = 1; int proto = 0, level = -1; int verify = 0, require = 0, request = 1; dprintf("Called"); -#if OPENSSL_VERSION_NUMBER < 0x10100000L && !defined(OPENSSL_NO_SSL2) && defined(NO_TLS1) && defined(NO_TLS1_1) && defined(NO_TLS1_2) && defined(NO_TLS1_3) && defined(NO_SSL3) && !defined(NO_SSL2) +#if OPENSSL_VERSION_NUMBER < 0x10100000L && !defined(OPENSSL_NO_SSL2) && !defined(NO_SSL2) && defined(NO_SSL3) && defined(NO_TLS1) && defined(NO_TLS1_1) && defined(NO_TLS1_2) && defined(NO_TLS1_3) ssl2 = 1; #endif -#if !defined(OPENSSL_NO_SSL3) && defined(NO_TLS1) && defined(NO_TLS1_1) && defined(NO_TLS1_2) && defined(NO_TLS1_3) && defined(NO_SSL2) && !defined(NO_SSL3) +#if !defined(OPENSSL_NO_SSL3) && !defined(NO_SSL3) && defined(NO_SSL2) && defined(NO_TLS1) && defined(NO_TLS1_1) && defined(NO_TLS1_2) && defined(NO_TLS1_3) ssl3 = 1; #endif #if defined(NO_TLS1) || defined(OPENSSL_NO_TLS1) tls1 = 0; #endif @@ -864,15 +800,12 @@ OPTOBJ("-password", password); OPTBOOL("-require", require); OPTBOOL("-request", request); OPTINT("-securitylevel", level); OPTBOOL("-server", server); -#ifndef OPENSSL_NO_TLSEXT OPTSTR("-servername", servername); OPTOBJ("-alpn", alpn); -#endif - OPTBOOL("-ssl2", ssl2); OPTBOOL("-ssl3", ssl3); OPTBOOL("-tls1", tls1); OPTBOOL("-tls1.1", tls1_1); OPTBOOL("-tls1.2", tls1_2); @@ -1004,11 +937,10 @@ Tcl_AppendResult(interp, "couldn't construct ssl session: ", REASON(), (char *) NULL); Tls_Free((char *) statePtr); return TCL_ERROR; } -#ifndef OPENSSL_NO_TLSEXT if (servername) { if (!SSL_set_tlsext_host_name(statePtr->ssl, servername) && require) { Tcl_AppendResult(interp, "setting TLS host name extension failed", (char *) NULL); Tls_Free((char *) statePtr); return TCL_ERROR; @@ -1051,11 +983,10 @@ return TCL_ERROR; } /* SSL_set_alpn_protos makes a copy of the protocol-list */ ckfree(protos); } -#endif /* * SSL Callbacks */ SSL_set_app_data(statePtr->ssl, (void *)statePtr); /* point back to us */ @@ -1209,26 +1140,26 @@ #if OPENSSL_VERSION_NUMBER < 0x10100000L && !defined(NO_SSL2) && !defined(OPENSSL_NO_SSL2) case TLS_PROTO_SSL2: method = SSLv2_method(); break; #endif -#if !defined(NO_SSL3) && !defined(OPENSSL_NO_SSL3) +#if !defined(NO_SSL3) && !defined(OPENSSL_NO_SSL3) && !defined(OPENSSL_NO_SSL3_METHOD) case TLS_PROTO_SSL3: method = SSLv3_method(); break; #endif -#if !defined(NO_TLS1) && !defined(OPENSSL_NO_TLS1) +#if !defined(NO_TLS1) && !defined(OPENSSL_NO_TLS1) && !defined(OPENSSL_NO_TLS1_METHOD) case TLS_PROTO_TLS1: method = TLSv1_method(); break; #endif -#if !defined(NO_TLS1_1) && !defined(OPENSSL_NO_TLS1_1) +#if !defined(NO_TLS1_1) && !defined(OPENSSL_NO_TLS1_1) && !defined(OPENSSL_NO_TLS1_1_METHOD) case TLS_PROTO_TLS1_1: method = TLSv1_1_method(); break; #endif -#if !defined(NO_TLS1_2) && !defined(OPENSSL_NO_TLS1_2) +#if !defined(NO_TLS1_2) && !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_TLS1_2_METHOD) case TLS_PROTO_TLS1_2: method = TLSv1_2_method(); break; #endif #if !defined(NO_TLS1_3) && !defined(OPENSSL_NO_TLS1_3) @@ -1240,16 +1171,12 @@ */ method = TLS_method(); break; #endif default: -#if OPENSSL_VERSION_NUMBER >= 0x10100000L /* Negotiate highest available SSL/TLS version */ method = TLS_method(); -#else - method = SSLv23_method(); -#endif #if OPENSSL_VERSION_NUMBER < 0x10100000L && !defined(NO_SSL2) && !defined(OPENSSL_NO_SSL2) off |= (ENABLED(proto, TLS_PROTO_SSL2) ? 0 : SSL_OP_NO_SSLv2); #endif #if !defined(NO_SSL3) && !defined(OPENSSL_NO_SSL3) off |= (ENABLED(proto, TLS_PROTO_SSL3) ? 0 : SSL_OP_NO_SSLv3); @@ -1312,14 +1239,11 @@ SSL_CTX_set_security_level(ctx, level); } /* set some callbacks */ SSL_CTX_set_default_passwd_cb(ctx, PasswordCallback); - -#ifndef BSAFE SSL_CTX_set_default_passwd_cb_userdata(ctx, (void *)statePtr); -#endif /* read a Diffie-Hellman parameters file, or use the built-in one */ #ifdef OPENSSL_NO_DH if (DHparams != NULL) { Tcl_AppendResult(interp, "DH parameter support not available", (char *) NULL); @@ -1484,14 +1408,12 @@ X509 *peer; Tcl_Obj *objPtr; Tcl_Channel chan; char *channelName, *ciphers; int mode; -#ifndef OPENSSL_NO_TLSEXT const unsigned char *proto; unsigned int len; -#endif dprintf("Called"); switch (objc) { case 2: @@ -1545,16 +1467,14 @@ if ((ciphers != NULL) && (strcmp(ciphers, "(NONE)") != 0)) { Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj("cipher", -1)); Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj(SSL_get_cipher(statePtr->ssl), -1)); } -#ifndef OPENSSL_NO_TLSEXT /* Report the selected protocol as a result of the negotiation */ SSL_get0_alpn_selected(statePtr->ssl, &proto, &len); Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj("alpn", -1)); Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj((char *)proto, (int)len)); -#endif Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj("version", -1)); Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj(SSL_get_version(statePtr->ssl), -1)); Tcl_SetObjResult(interp, objPtr); return TCL_OK; @@ -1576,16 +1496,13 @@ Tcl_Channel chan; /* The channel to set a mode on. */ State *statePtr; /* client state for ssl socket */ Tcl_Obj *objPtr; const SSL *ssl; const SSL_CIPHER *cipher; - -#if !defined(OPENSSL_NO_TLSEXT) && OPENSSL_VERSION_NUMBER >= 0x10002000L const unsigned char *proto; unsigned int len; -#endif -#if defined(HAVE_SSL_COMPRESSION) && OPENSSL_VERSION_NUMBER >= 0x10002000L +#if defined(HAVE_SSL_COMPRESSION) const COMP_METHOD *comp; #endif if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "channel"); @@ -1661,22 +1578,20 @@ Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj("renegotiation", -1)); Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj( SSL_get_secure_renegotiation_support(ssl) ? "allowed" : "disallowed", -1)); -#if !defined(OPENSSL_NO_TLSEXT) && OPENSSL_VERSION_NUMBER >= 0x10002000L /* Report the selected protocol as a result of the negotiation */ SSL_get0_alpn_selected(ssl, &proto, &len); Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj("alpn", -1)); Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj((char *)proto, (int)len)); -#endif /* Session info */ Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj("session_reused", -1)); Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewIntObj(SSL_session_reused(ssl))); -#if defined(HAVE_SSL_COMPRESSION) && OPENSSL_VERSION_NUMBER >= 0x10002000L +#if defined(HAVE_SSL_COMPRESSION) /* Compression info */ comp = SSL_get_current_compression(ssl); if (comp != NULL) { expansion = SSL_get_current_expansion(ssl); Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj("compression", -1)); @@ -1763,13 +1678,11 @@ char *k_C="",*k_ST="",*k_L="",*k_O="",*k_OU="",*k_CN="",*k_Email=""; char *keyout,*pemout,*str; int keysize,serial=0,days=365; -#if OPENSSL_VERSION_NUMBER <= 0x10100000L - RSA *rsa = NULL; -#elif OPENSSL_VERSION_NUMBER < 0x30000000L +#if OPENSSL_VERSION_NUMBER < 0x30000000L BIGNUM *bne = NULL; RSA *rsa = NULL; #else EVP_PKEY_CTX *ctx = NULL; #endif @@ -1826,17 +1739,11 @@ return TCL_ERROR; } } } -#if OPENSSL_VERSION_NUMBER <= 0x10100000L - pkey = EVP_PKEY_new(); - rsa = RSA_generate_key(keysize, 0x10001, NULL, NULL); - if (pkey == NULL || rsa == NULL || !EVP_PKEY_assign_RSA(pkey, rsa)) { - EVP_PKEY_free(pkey); - /* RSA_free(rsa); freed by EVP_PKEY_free */ -#elif OPENSSL_VERSION_NUMBER < 0x30000000L +#if OPENSSL_VERSION_NUMBER < 0x30000000L bne = BN_new(); rsa = RSA_new(); pkey = EVP_PKEY_new(); if (bne == NULL || rsa == NULL || pkey == NULL || !BN_set_word(bne,RSA_F4) || !RSA_generate_key_ex(rsa, keysize, bne, NULL) || !EVP_PKEY_assign_RSA(pkey, rsa)) { @@ -1872,25 +1779,20 @@ } if ((cert=X509_new())==NULL) { Tcl_SetResult(interp,"Error generating certificate request",NULL); EVP_PKEY_free(pkey); -#if OPENSSL_VERSION_NUMBER > 0x10100000L && OPENSSL_VERSION_NUMBER < 0x30000000L +#if OPENSSL_VERSION_NUMBER < 0x30000000L BN_free(bne); #endif return(TCL_ERROR); } X509_set_version(cert,2); ASN1_INTEGER_set(X509_get_serialNumber(cert),serial); -#if OPENSSL_VERSION_NUMBER < 0x10100000L - X509_gmtime_adj(X509_get_notBefore(cert),0); - X509_gmtime_adj(X509_get_notAfter(cert),(long)60*60*24*days); -#else X509_gmtime_adj(X509_getm_notBefore(cert),0); X509_gmtime_adj(X509_getm_notAfter(cert),(long)60*60*24*days); -#endif X509_set_pubkey(cert,pkey); name=X509_get_subject_name(cert); X509_NAME_add_entry_by_txt(name,"C", MBSTRING_ASC, (const unsigned char *) k_C, -1, -1, 0); @@ -1904,11 +1806,11 @@ X509_set_subject_name(cert,name); if (!X509_sign(cert,pkey,EVP_sha256())) { X509_free(cert); EVP_PKEY_free(pkey); -#if OPENSSL_VERSION_NUMBER > 0x10100000L && OPENSSL_VERSION_NUMBER < 0x30000000L +#if OPENSSL_VERSION_NUMBER < 0x30000000L BN_free(bne); #endif Tcl_SetResult(interp,"Error signing certificate",NULL); return TCL_ERROR; } @@ -1929,11 +1831,11 @@ BIO_free_all(out); } X509_free(cert); EVP_PKEY_free(pkey); -#if OPENSSL_VERSION_NUMBER > 0x10100000L && OPENSSL_VERSION_NUMBER < 0x30000000L +#if OPENSSL_VERSION_NUMBER < 0x30000000L BN_free(bne); #endif } } break; @@ -2141,18 +2043,10 @@ dprintf("Asked to uninitialize"); #if defined(OPENSSL_THREADS) && defined(TCL_THREADS) Tcl_MutexLock(&init_mx); -#if OPENSSL_VERSION_NUMBER < 0x10000000L - CRYPTO_set_locking_callback(NULL); - CRYPTO_set_id_callback(NULL); -#elif OPENSSL_VERSION_NUMBER < 0x10100000L - CRYPTO_set_locking_callback(NULL); - CRYPTO_THREADID_set_callback(NULL) -#endif - if (locks) { free(locks); locks = NULL; locksCount = 0; } @@ -2177,46 +2071,19 @@ Tcl_MutexLock(&init_mx); #endif initialized = 1; #if defined(OPENSSL_THREADS) && defined(TCL_THREADS) -#if OPENSSL_VERSION_NUMBER < 0x10100000L - num_locks = CRYPTO_num_locks(); -#else num_locks = 1; -#endif locksCount = (int) num_locks; locks = malloc(sizeof(*locks) * num_locks); memset(locks, 0, sizeof(*locks) * num_locks); - -#if OPENSSL_VERSION_NUMBER < 0x10000000L - CRYPTO_set_locking_callback(CryptoThreadLockCallback); - CRYPTO_set_id_callback(CryptoThreadIdCallback); -#elif OPENSSL_VERSION_NUMBER < 0x10100000L - CRYPTO_set_locking_callback(CryptoThreadLockCallback); - CRYPTO_THREADID_set_callback(CryptoThreadIdCallback) -#endif -#endif - -# if OPENSSL_VERSION_NUMBER < 0x10100000L - if (SSL_library_init() != 1) { - status = TCL_ERROR; - goto done; - } -#else +#endif + /* Initialize BOTH libcrypto and libssl. */ OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS | OPENSSL_INIT_LOAD_CRYPTO_STRINGS | OPENSSL_INIT_ADD_ALL_CIPHERS | OPENSSL_INIT_ADD_ALL_DIGESTS, NULL); -#endif - -# if OPENSSL_VERSION_NUMBER < 0x10100000L - SSL_load_error_strings(); - ERR_load_crypto_strings(); -#else - /* Only initialize libcrypto */ - OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL); -#endif BIO_new_tcl(NULL, 0); #if 0 /* @@ -2241,14 +2108,11 @@ } RAND_seed(rnd_seed, sizeof(rnd_seed)); } while (RAND_status() != 1); #endif -# if OPENSSL_VERSION_NUMBER < 0x10100000L -done: -#endif #if defined(OPENSSL_THREADS) && defined(TCL_THREADS) Tcl_MutexUnlock(&init_mx); #endif return(status); }