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}