Index: doc/tls.html ================================================================== --- doc/tls.html +++ doc/tls.html @@ -178,10 +178,17 @@ (default is true)
-require bool
Require a valid certificate from peer during SSL handshake. If this is set to true, then -request must also be set to true. (default is false)
+
-securitylevel integer
+
Set security level. Must be 0 to 5. The security level affects + cipher suite encryption algorithms, supported ECC curves, + supported signature algorithms, DH parameter sizes, certificate + key sizes and signature algorithms. The default is 1. + Level 3 and higher disable support for session tickets and only + accept cipher suites that provide forward secrecy.
-server bool
Handshake as server if true, else handshake as client. (default is false)
-servername host
Specify server hostname. Only available if the OpenSSL library @@ -269,11 +276,13 @@
State of the connection: initializing, handshake, established
server name
The name of the connected to server.
protocol version
The protocol version used for the connection: - SSL2, SSL3, TLS1, TLS1.1, TLS1.2, TLS1.3, or unknown
+ SSL2, SSL3, TLS1, TLS1.1, TLS1.2, TLS1.3, or unknown. +
securitylevel level
+
The security level used for selection of ciphers, key size, etc.
cipher cipher
The current cipher in use for the connection.
standard_name name
The standard RFC name of cipher.
bits n
Index: generic/tls.c ================================================================== --- generic/tls.c +++ generic/tls.c @@ -42,11 +42,11 @@ #define REASON() ERR_reason_error_string(ERR_get_error()) static SSL_CTX *CTX_Init(State *statePtr, int isServer, int proto, char *key, char *certfile, unsigned char *key_asn1, unsigned char *cert_asn1, int key_asn1_len, int cert_asn1_len, char *CAdir, char *CAfile, - char *ciphers, char *ciphersuites, char *DHparams); + char *ciphers, char *ciphersuites, int level, char *DHparams); static int TlsLibInit(int uninitialize); #define TLS_PROTO_SSL2 0x01 #define TLS_PROTO_SSL3 0x02 @@ -610,11 +610,11 @@ const SSL_CIPHER *c = sk_SSL_CIPHER_value(sk, i); if (c == NULL) continue; /* textual description of the cipher */ if (SSL_CIPHER_description(c, buf, sizeof(buf)) != NULL) { - Tcl_AppendToObj(objPtr, buf, strlen(buf)); + Tcl_AppendToObj(objPtr, buf, (int) strlen(buf)); } else { Tcl_AppendToObj(objPtr, "UNKNOWN\n", 8); } } } @@ -804,11 +804,11 @@ 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; + 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) @@ -853,18 +853,20 @@ OPTSTR("-cadir", CAdir); OPTSTR("-cafile", CAfile); OPTSTR("-certfile", certfile); OPTSTR("-cipher", ciphers); + OPTSTR("-ciphers", ciphers); OPTSTR("-ciphersuites", ciphersuites); OPTOBJ("-command", script); OPTSTR("-dhparams", DHparams); OPTSTR("-keyfile", keyfile); OPTSTR("-model", model); 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 @@ -876,11 +878,11 @@ OPTBOOL("-tls1.2", tls1_2); OPTBOOL("-tls1.3", tls1_3); OPTBYTE("-cert", cert, cert_len); OPTBYTE("-key", key, key_len); - OPTBAD("option", "-alpn, -cadir, -cafile, -cert, -certfile, -cipher, -ciphersuites, -command, -dhparams, -key, -keyfile, -model, -password, -require, -request, -server, -servername, -ssl2, -ssl3, -tls1, -tls1.1, -tls1.2, or -tls1.3"); + OPTBAD("option", "-alpn, -cadir, -cafile, -cert, -certfile, -cipher, -ciphersuites, -command, -dhparams, -key, -keyfile, -model, -password, -require, -request, -securitylevel, -server, -servername, -ssl2, -ssl3, -tls1, -tls1.1, -tls1.2, or -tls1.3"); return TCL_ERROR; } if (request) verify |= SSL_VERIFY_CLIENT_ONCE | SSL_VERIFY_PEER; if (request && require) verify |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; @@ -951,11 +953,11 @@ return TCL_ERROR; } ctx = ((State *)Tcl_GetChannelInstanceData(chan))->ctx; } else { if ((ctx = CTX_Init(statePtr, server, proto, keyfile, certfile, key, cert, - key_len, cert_len, CAdir, CAfile, ciphers, ciphersuites, DHparams)) == (SSL_CTX*)0) { + key_len, cert_len, CAdir, CAfile, ciphers, ciphersuites, level, DHparams)) == (SSL_CTX*)0) { Tls_Free((char *) statePtr); return TCL_ERROR; } } @@ -1147,11 +1149,11 @@ *------------------------------------------------------------------- */ static SSL_CTX * CTX_Init(State *statePtr, int isServer, int proto, char *keyfile, char *certfile, unsigned char *key, unsigned char *cert, int key_len, int cert_len, char *CAdir, - char *CAfile, char *ciphers, char *ciphersuites, char *DHparams) { + char *CAfile, char *ciphers, char *ciphersuites, int level, char *DHparams) { Tcl_Interp *interp = statePtr->interp; SSL_CTX *ctx = NULL; Tcl_DString ds; Tcl_DString ds1; int off = 0; @@ -1294,17 +1296,23 @@ #if OPENSSL_VERSION_NUMBER < 0x10101000L SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); /* handle new handshakes in background */ #endif SSL_CTX_sess_set_cache_size(ctx, 128); - /* Set user defined ciphers and cipher suites */ + /* Set user defined ciphers, cipher suites, and security level */ if (((ciphers != NULL) && !SSL_CTX_set_cipher_list(ctx, ciphers)) || \ ((ciphersuites != NULL) && !SSL_CTX_set_ciphersuites(ctx, ciphersuites))) { Tcl_AppendResult(interp, "Set ciphers failed", (char *) NULL); SSL_CTX_free(ctx); return (SSL_CTX *)0; } + + /* Set security level */ + if (level > -1 && level < 6) { + /* SSL_set_security_level */ + SSL_CTX_set_security_level(ctx, level); + } /* set some callbacks */ SSL_CTX_set_default_passwd_cb(ctx, PasswordCallback); #ifndef BSAFE @@ -1611,17 +1619,21 @@ } else { Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj("initializing", -1)); } /* Get server name */ - Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj("server", -1)); + Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj("servername", -1)); Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj(SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name), -1)); /* Get protocol */ Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj("protocol", -1)); Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj(SSL_get_version(ssl), -1)); + /* Get security level */ + Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj("securitylevel", -1)); + Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewIntObj(SSL_get_security_level(ssl))); + /* Get cipher */ cipher = SSL_get_current_cipher(ssl); if (cipher != NULL) { char buf[BUFSIZ] = {0}; int bits, alg_bits; Index: library/tls.tcl ================================================================== --- library/tls.tcl +++ library/tls.tcl @@ -43,10 +43,11 @@ {* -key iopts 1} {* -keyfile iopts 1} {* -password iopts 1} {* -request iopts 1} {* -require iopts 1} + {* -securitylevel iopts 1} {* -autoservername discardOpts 1} {* -servername iopts 1} {* -alpn iopts 1} {* -ssl2 iopts 1} {* -ssl3 iopts 1}