Index: tests/badssl.csv ================================================================== --- tests/badssl.csv +++ tests/badssl.csv @@ -1,72 +1,67 @@ # Group,Name,Constraints,Setup,Body,Cleanup,Match,Result,Output,Error Output,Return Codes command,package require tls,,,,,,,,, -command,,,,,,,,,, -command,# Find default CA certificates directory,,,,,,,,, -command,if {[info exists ::env(SSL_CERT_FILE)]} {set ::cafile $::env(SSL_CERT_FILE)} else {set ::cafile [file normalize {C:\Users\Brian\Documents\Source\Build\SSL-1.1\certs\cacert.pem}]},,,,,,,,, -command,,,,,,,,,, +,,,,,,,,,, command,# Constraints,,,,,,,,, -command,set protocols [list ssl2 ssl3 tls1 tls1.1 tls1.2 tls1.3],,,,,,,,, -command,foreach protocol $protocols {::tcltest::testConstraint $protocol 0},,,,,,,,, -command,foreach protocol [::tls::protocols] {::tcltest::testConstraint $protocol 1},,,,,,,,, -command,,,,,,,,,, +command,source [file join [file dirname [info script]] common.tcl],,,,,,,,, +,,,,,,,,,, command,# Helper functions,,,,,,,,, -command,"proc badssl {url} {set port 443;lassign [split $url "":""] url port;if {$port eq """"} {set port 443};set ch [tls::socket -autoservername 1 -require 1 -cafile $::cafile $url $port];if {[catch {tls::handshake $ch} err]} {close $ch;return -code error $err} else {close $ch}}",,,,,,,,, -command,,,,,,,,,, +command,"proc badssl {url} {set port 443;lassign [split $url "":""] url port;if {$port eq """"} {set port 443};set cmd [list tls::socket -autoservername 1 -require 1];if {[info exists ::env(SSL_CERT_FILE)]} {lappend cmd -cafile $::env(SSL_CERT_FILE)};lappend cmd $url $port;set ch [eval $cmd];if {[catch {tls::handshake $ch} err]} {close $ch;return -code error $err} else {close $ch}}",,,,,,,,, +,,,,,,,,,, command,# BadSSL.com Tests,,,,,,,,, -BadSSL,1000-sans,,,badssl 1000-sans.badssl.com,,,handshake failed: certificate verify failed due to: certificate has expired,,,1 +BadSSL,1000-sans,,,badssl 1000-sans.badssl.com,,,"handshake failed: certificate verify failed due to ""certificate has expired""",,,1 BadSSL,10000-sans,,,badssl 10000-sans.badssl.com,,,handshake failed: excessive message size,,,1 BadSSL,3des,,,badssl 3des.badssl.com,,,handshake failed: sslv3 alert handshake failure,,,1 -BadSSL,captive-portal,,,badssl captive-portal.badssl.com,,,handshake failed: certificate verify failed due to: Hostname mismatch,,,1 +BadSSL,captive-portal,,,badssl captive-portal.badssl.com,,,"handshake failed: certificate verify failed due to ""Hostname mismatch""",,,1 BadSSL,cbc,,,badssl cbc.badssl.com,,,,,, BadSSL,client-cert-missing,,,badssl client-cert-missing.badssl.com,,,,,, BadSSL,client,,,badssl client.badssl.com,,,,,, BadSSL,dh-composite,,,badssl dh-composite.badssl.com,,,,,, BadSSL,dh-small-subgroup,,,badssl dh-small-subgroup.badssl.com,,,,,, BadSSL,dh480,,,badssl dh480.badssl.com,,,handshake failed: dh key too small,,,1 BadSSL,dh512,,,badssl dh512.badssl.com,,,handshake failed: dh key too small,,,1 BadSSL,dh1024,,,badssl dh1024.badssl.com,,,,,, BadSSL,dh2048,,,badssl dh2048.badssl.com,,,,,, -BadSSL,dsdtestprovider,,,badssl dsdtestprovider.badssl.com,,,handshake failed: certificate verify failed due to: unable to get local issuer certificate,,,1 +BadSSL,dsdtestprovider,,,badssl dsdtestprovider.badssl.com,,,"handshake failed: certificate verify failed due to ""unable to get local issuer certificate""",,,1 BadSSL,ecc256,,,badssl ecc256.badssl.com,,,,,, BadSSL,ecc384,,,badssl ecc384.badssl.com,,,,,, -BadSSL,edellroot,,,badssl edellroot.badssl.com,,,handshake failed: certificate verify failed due to: unable to get local issuer certificate,,,1 -BadSSL,expired,,,badssl expired.badssl.com,,,handshake failed: certificate verify failed due to: certificate has expired,,,1 -BadSSL,extended-validation,,,badssl extended-validation.badssl.com,,,handshake failed: certificate verify failed due to: certificate has expired,,,1 +BadSSL,edellroot,,,badssl edellroot.badssl.com,,,"handshake failed: certificate verify failed due to ""unable to get local issuer certificate""",,,1 +BadSSL,expired,,,badssl expired.badssl.com,,,"handshake failed: certificate verify failed due to ""certificate has expired""",,,1 +BadSSL,extended-validation,,,badssl extended-validation.badssl.com,,,"handshake failed: certificate verify failed due to ""certificate has expired""",,,1 BadSSL,hsts,,,badssl hsts.badssl.com,,,,,, BadSSL,https-everywhere,,,badssl https-everywhere.badssl.com,,,,,, -BadSSL,incomplete-chain,,,badssl incomplete-chain.badssl.com,,,handshake failed: certificate verify failed due to: unable to get local issuer certificate,,,1 -BadSSL,invalid-expected-sct,,,badssl invalid-expected-sct.badssl.com,,,handshake failed: certificate verify failed due to: unable to get local issuer certificate,,,1 +BadSSL,incomplete-chain,,,badssl incomplete-chain.badssl.com,,,"handshake failed: certificate verify failed due to ""unable to get local issuer certificate""",,,1 +BadSSL,invalid-expected-sct,,,badssl invalid-expected-sct.badssl.com,,,"handshake failed: certificate verify failed due to ""unable to get local issuer certificate""",,,1 BadSSL,long-extended-subdomain-name-containing-many-letters-and-dashes,,,badssl long-extended-subdomain-name-containing-many-letters-and-dashes.badssl.com,,,,,, BadSSL,longextendedsubdomainnamewithoutdashesinordertotestwordwrapping,,,badssl longextendedsubdomainnamewithoutdashesinordertotestwordwrapping.badssl.com,,,,,, -BadSSL,mitm-software,,,badssl mitm-software.badssl.com,,,handshake failed: certificate verify failed due to: unable to get local issuer certificate,,,1 -BadSSL,no-common-name,,,badssl no-common-name.badssl.com,,,handshake failed: certificate verify failed due to: certificate has expired,,,1 -BadSSL,no-sct,,,badssl no-sct.badssl.com,,,handshake failed: certificate verify failed due to: unable to get local issuer certificate,,,1 -BadSSL,no-subject,,,badssl no-subject.badssl.com,,,handshake failed: certificate verify failed due to: certificate has expired,,,1 +BadSSL,mitm-software,,,badssl mitm-software.badssl.com,,,"handshake failed: certificate verify failed due to ""unable to get local issuer certificate""",,,1 +BadSSL,no-common-name,,,badssl no-common-name.badssl.com,,,"handshake failed: certificate verify failed due to ""certificate has expired""",,,1 +BadSSL,no-sct,,,badssl no-sct.badssl.com,,,"handshake failed: certificate verify failed due to ""unable to get local issuer certificate""",,,1 +BadSSL,no-subject,,,badssl no-subject.badssl.com,,,"handshake failed: certificate verify failed due to ""certificate has expired""",,,1 BadSSL,null,,,badssl null.badssl.com,,,handshake failed: sslv3 alert handshake failure,,,1 BadSSL,pinning-test,,,badssl pinning-test.badssl.com,,,,,, -BadSSL,preact-cli,,,badssl preact-cli.badssl.com,,,handshake failed: certificate verify failed due to: unable to get local issuer certificate,,,1 +BadSSL,preact-cli,,,badssl preact-cli.badssl.com,,,"handshake failed: certificate verify failed due to ""unable to get local issuer certificate""",,,1 BadSSL,preloaded-hsts,,,badssl preloaded-hsts.badssl.com,,,,,, BadSSL,rc4-md5,,,badssl rc4-md5.badssl.com,,,handshake failed: sslv3 alert handshake failure,,,1 BadSSL,rc4,,,badssl rc4.badssl.com,,,handshake failed: sslv3 alert handshake failure,,,1 -BadSSL,revoked,,,badssl revoked.badssl.com,,,handshake failed: certificate verify failed due to: certificate has expired,,,1 +BadSSL,revoked,,,badssl revoked.badssl.com,,,"handshake failed: certificate verify failed due to ""certificate has expired""",,,1 BadSSL,rsa2048,,,badssl rsa2048.badssl.com,,,,,, BadSSL,rsa4096,,,badssl rsa4096.badssl.com,,,,,, BadSSL,rsa8192,,,badssl rsa8192.badssl.com,,,,,, -BadSSL,self-signed,,,badssl self-signed.badssl.com,,,handshake failed: certificate verify failed due to: self signed certificate,,,1 -BadSSL,sha1-2016,,,badssl sha1-2016.badssl.com,,,handshake failed: certificate verify failed due to: unable to get local issuer certificate,,,1 -BadSSL,sha1-2017,,,badssl sha1-2017.badssl.com,,,handshake failed: certificate verify failed due to: certificate has expired,,,1 -BadSSL,sha1-intermediate,,,badssl sha1-intermediate.badssl.com,,,handshake failed: certificate verify failed due to: unable to get local issuer certificate,,,1 +BadSSL,self-signed,,,badssl self-signed.badssl.com,,,"handshake failed: certificate verify failed due to ""self signed certificate""",,,1 +BadSSL,sha1-2016,,,badssl sha1-2016.badssl.com,,,"handshake failed: certificate verify failed due to ""unable to get local issuer certificate""",,,1 +BadSSL,sha1-2017,,,badssl sha1-2017.badssl.com,,,"handshake failed: certificate verify failed due to ""certificate has expired""",,,1 +BadSSL,sha1-intermediate,,,badssl sha1-intermediate.badssl.com,,,"handshake failed: certificate verify failed due to ""unable to get local issuer certificate""",,,1 BadSSL,sha256,,,badssl sha256.badssl.com,,,,,, -BadSSL,sha384,,,badssl sha384.badssl.com,,,handshake failed: certificate verify failed due to: certificate has expired,,,1 -BadSSL,sha512,,,badssl sha512.badssl.com,,,handshake failed: certificate verify failed due to: certificate has expired,,,1 +BadSSL,sha384,,,badssl sha384.badssl.com,,,"handshake failed: certificate verify failed due to ""certificate has expired""",,,1 +BadSSL,sha512,,,badssl sha512.badssl.com,,,"handshake failed: certificate verify failed due to ""certificate has expired""",,,1 BadSSL,static-rsa,,,badssl static-rsa.badssl.com,,,,,, -BadSSL,subdomain.preloaded-hsts,,,badssl subdomain.preloaded-hsts.badssl.com,,,handshake failed: certificate verify failed due to: Hostname mismatch,,,1 -BadSSL,superfish,,,badssl superfish.badssl.com,,,handshake failed: certificate verify failed due to: unable to get local issuer certificate,,,1 +BadSSL,subdomain.preloaded-hsts,,,badssl subdomain.preloaded-hsts.badssl.com,,,"handshake failed: certificate verify failed due to ""Hostname mismatch""",,,1 +BadSSL,superfish,,,badssl superfish.badssl.com,,,"handshake failed: certificate verify failed due to ""unable to get local issuer certificate""",,,1 BadSSL,tls-v1-0:1010,tls1,,badssl tls-v1-0.badssl.com:1010,,,,,, BadSSL,tls-v1-1:1011,tls1.1,,badssl tls-v1-1.badssl.com:1011,,,,,, BadSSL,tls-v1-2:1012,tls1.2,,badssl tls-v1-2.badssl.com:1012,,,,,, -BadSSL,untrusted-root,,,badssl untrusted-root.badssl.com,,,handshake failed: certificate verify failed due to: self signed certificate in certificate chain,,,1 +BadSSL,untrusted-root,,,badssl untrusted-root.badssl.com,,,"handshake failed: certificate verify failed due to ""self signed certificate in certificate chain""",,,1 BadSSL,upgrade,,,badssl upgrade.badssl.com,,,,,, -BadSSL,webpack-dev-server,,,badssl webpack-dev-server.badssl.com,,,handshake failed: certificate verify failed due to: unable to get local issuer certificate,,,1 -BadSSL,wrong.host,,,badssl wrong.host.badssl.com,,,handshake failed: certificate verify failed due to: Hostname mismatch,,,1 +BadSSL,webpack-dev-server,,,badssl webpack-dev-server.badssl.com,,,"handshake failed: certificate verify failed due to ""unable to get local issuer certificate""",,,1 +BadSSL,wrong.host,,,badssl wrong.host.badssl.com,,,"handshake failed: certificate verify failed due to ""Hostname mismatch""",,,1 BadSSL,mozilla-modern,,,badssl mozilla-modern.badssl.com,,,,,, Index: tests/badssl.test ================================================================== --- tests/badssl.test +++ tests/badssl.test @@ -8,27 +8,22 @@ set auto_path [concat [list [file dirname [file dirname [info script]]]] $auto_path] package require tls -# Find default CA certificates directory -if {[info exists ::env(SSL_CERT_FILE)]} {set ::cafile $::env(SSL_CERT_FILE)} else {set ::cafile [file normalize {C:\Users\Brian\Documents\Source\Build\SSL-1.1\certs\cacert.pem}]} - # Constraints -set protocols [list ssl2 ssl3 tls1 tls1.1 tls1.2 tls1.3] -foreach protocol $protocols {::tcltest::testConstraint $protocol 0} -foreach protocol [::tls::protocols] {::tcltest::testConstraint $protocol 1} +source [file join [file dirname [info script]] common.tcl] # Helper functions -proc badssl {url} {set port 443;lassign [split $url ":"] url port;if {$port eq ""} {set port 443};set ch [tls::socket -autoservername 1 -require 1 -cafile $::cafile $url $port];if {[catch {tls::handshake $ch} err]} {close $ch;return -code error $err} else {close $ch}} +proc badssl {url} {set port 443;lassign [split $url ":"] url port;if {$port eq ""} {set port 443};set cmd [list tls::socket -autoservername 1 -require 1];if {[info exists ::env(SSL_CERT_FILE)]} {lappend cmd -cafile $::env(SSL_CERT_FILE)};lappend cmd $url $port;set ch [eval $cmd];if {[catch {tls::handshake $ch} err]} {close $ch;return -code error $err} else {close $ch}} # BadSSL.com Tests test BadSSL-1.1 {1000-sans} -body { badssl 1000-sans.badssl.com - } -result {handshake failed: certificate verify failed due to: certificate has expired} -returnCodes {1} + } -result {handshake failed: certificate verify failed due to "certificate has expired"} -returnCodes {1} test BadSSL-1.2 {10000-sans} -body { badssl 10000-sans.badssl.com } -result {handshake failed: excessive message size} -returnCodes {1} @@ -36,11 +31,11 @@ badssl 3des.badssl.com } -result {handshake failed: sslv3 alert handshake failure} -returnCodes {1} test BadSSL-1.4 {captive-portal} -body { badssl captive-portal.badssl.com - } -result {handshake failed: certificate verify failed due to: Hostname mismatch} -returnCodes {1} + } -result {handshake failed: certificate verify failed due to "Hostname mismatch"} -returnCodes {1} test BadSSL-1.5 {cbc} -body { badssl cbc.badssl.com } @@ -76,11 +71,11 @@ badssl dh2048.badssl.com } test BadSSL-1.14 {dsdtestprovider} -body { badssl dsdtestprovider.badssl.com - } -result {handshake failed: certificate verify failed due to: unable to get local issuer certificate} -returnCodes {1} + } -result {handshake failed: certificate verify failed due to "unable to get local issuer certificate"} -returnCodes {1} test BadSSL-1.15 {ecc256} -body { badssl ecc256.badssl.com } @@ -88,19 +83,19 @@ badssl ecc384.badssl.com } test BadSSL-1.17 {edellroot} -body { badssl edellroot.badssl.com - } -result {handshake failed: certificate verify failed due to: unable to get local issuer certificate} -returnCodes {1} + } -result {handshake failed: certificate verify failed due to "unable to get local issuer certificate"} -returnCodes {1} test BadSSL-1.18 {expired} -body { badssl expired.badssl.com - } -result {handshake failed: certificate verify failed due to: certificate has expired} -returnCodes {1} + } -result {handshake failed: certificate verify failed due to "certificate has expired"} -returnCodes {1} test BadSSL-1.19 {extended-validation} -body { badssl extended-validation.badssl.com - } -result {handshake failed: certificate verify failed due to: certificate has expired} -returnCodes {1} + } -result {handshake failed: certificate verify failed due to "certificate has expired"} -returnCodes {1} test BadSSL-1.20 {hsts} -body { badssl hsts.badssl.com } @@ -108,15 +103,15 @@ badssl https-everywhere.badssl.com } test BadSSL-1.22 {incomplete-chain} -body { badssl incomplete-chain.badssl.com - } -result {handshake failed: certificate verify failed due to: unable to get local issuer certificate} -returnCodes {1} + } -result {handshake failed: certificate verify failed due to "unable to get local issuer certificate"} -returnCodes {1} test BadSSL-1.23 {invalid-expected-sct} -body { badssl invalid-expected-sct.badssl.com - } -result {handshake failed: certificate verify failed due to: unable to get local issuer certificate} -returnCodes {1} + } -result {handshake failed: certificate verify failed due to "unable to get local issuer certificate"} -returnCodes {1} test BadSSL-1.24 {long-extended-subdomain-name-containing-many-letters-and-dashes} -body { badssl long-extended-subdomain-name-containing-many-letters-and-dashes.badssl.com } @@ -124,23 +119,23 @@ badssl longextendedsubdomainnamewithoutdashesinordertotestwordwrapping.badssl.com } test BadSSL-1.26 {mitm-software} -body { badssl mitm-software.badssl.com - } -result {handshake failed: certificate verify failed due to: unable to get local issuer certificate} -returnCodes {1} + } -result {handshake failed: certificate verify failed due to "unable to get local issuer certificate"} -returnCodes {1} test BadSSL-1.27 {no-common-name} -body { badssl no-common-name.badssl.com - } -result {handshake failed: certificate verify failed due to: certificate has expired} -returnCodes {1} + } -result {handshake failed: certificate verify failed due to "certificate has expired"} -returnCodes {1} test BadSSL-1.28 {no-sct} -body { badssl no-sct.badssl.com - } -result {handshake failed: certificate verify failed due to: unable to get local issuer certificate} -returnCodes {1} + } -result {handshake failed: certificate verify failed due to "unable to get local issuer certificate"} -returnCodes {1} test BadSSL-1.29 {no-subject} -body { badssl no-subject.badssl.com - } -result {handshake failed: certificate verify failed due to: certificate has expired} -returnCodes {1} + } -result {handshake failed: certificate verify failed due to "certificate has expired"} -returnCodes {1} test BadSSL-1.30 {null} -body { badssl null.badssl.com } -result {handshake failed: sslv3 alert handshake failure} -returnCodes {1} @@ -148,11 +143,11 @@ badssl pinning-test.badssl.com } test BadSSL-1.32 {preact-cli} -body { badssl preact-cli.badssl.com - } -result {handshake failed: certificate verify failed due to: unable to get local issuer certificate} -returnCodes {1} + } -result {handshake failed: certificate verify failed due to "unable to get local issuer certificate"} -returnCodes {1} test BadSSL-1.33 {preloaded-hsts} -body { badssl preloaded-hsts.badssl.com } @@ -164,11 +159,11 @@ badssl rc4.badssl.com } -result {handshake failed: sslv3 alert handshake failure} -returnCodes {1} test BadSSL-1.36 {revoked} -body { badssl revoked.badssl.com - } -result {handshake failed: certificate verify failed due to: certificate has expired} -returnCodes {1} + } -result {handshake failed: certificate verify failed due to "certificate has expired"} -returnCodes {1} test BadSSL-1.37 {rsa2048} -body { badssl rsa2048.badssl.com } @@ -180,47 +175,47 @@ badssl rsa8192.badssl.com } test BadSSL-1.40 {self-signed} -body { badssl self-signed.badssl.com - } -result {handshake failed: certificate verify failed due to: self signed certificate} -returnCodes {1} + } -result {handshake failed: certificate verify failed due to "self signed certificate"} -returnCodes {1} test BadSSL-1.41 {sha1-2016} -body { badssl sha1-2016.badssl.com - } -result {handshake failed: certificate verify failed due to: unable to get local issuer certificate} -returnCodes {1} + } -result {handshake failed: certificate verify failed due to "unable to get local issuer certificate"} -returnCodes {1} test BadSSL-1.42 {sha1-2017} -body { badssl sha1-2017.badssl.com - } -result {handshake failed: certificate verify failed due to: certificate has expired} -returnCodes {1} + } -result {handshake failed: certificate verify failed due to "certificate has expired"} -returnCodes {1} test BadSSL-1.43 {sha1-intermediate} -body { badssl sha1-intermediate.badssl.com - } -result {handshake failed: certificate verify failed due to: unable to get local issuer certificate} -returnCodes {1} + } -result {handshake failed: certificate verify failed due to "unable to get local issuer certificate"} -returnCodes {1} test BadSSL-1.44 {sha256} -body { badssl sha256.badssl.com } test BadSSL-1.45 {sha384} -body { badssl sha384.badssl.com - } -result {handshake failed: certificate verify failed due to: certificate has expired} -returnCodes {1} + } -result {handshake failed: certificate verify failed due to "certificate has expired"} -returnCodes {1} test BadSSL-1.46 {sha512} -body { badssl sha512.badssl.com - } -result {handshake failed: certificate verify failed due to: certificate has expired} -returnCodes {1} + } -result {handshake failed: certificate verify failed due to "certificate has expired"} -returnCodes {1} test BadSSL-1.47 {static-rsa} -body { badssl static-rsa.badssl.com } test BadSSL-1.48 {subdomain.preloaded-hsts} -body { badssl subdomain.preloaded-hsts.badssl.com - } -result {handshake failed: certificate verify failed due to: Hostname mismatch} -returnCodes {1} + } -result {handshake failed: certificate verify failed due to "Hostname mismatch"} -returnCodes {1} test BadSSL-1.49 {superfish} -body { badssl superfish.badssl.com - } -result {handshake failed: certificate verify failed due to: unable to get local issuer certificate} -returnCodes {1} + } -result {handshake failed: certificate verify failed due to "unable to get local issuer certificate"} -returnCodes {1} test BadSSL-1.50 {tls-v1-0:1010} -constraints {tls1} -body { badssl tls-v1-0.badssl.com:1010 } @@ -232,26 +227,26 @@ badssl tls-v1-2.badssl.com:1012 } test BadSSL-1.53 {untrusted-root} -body { badssl untrusted-root.badssl.com - } -result {handshake failed: certificate verify failed due to: self signed certificate in certificate chain} -returnCodes {1} + } -result {handshake failed: certificate verify failed due to "self signed certificate in certificate chain"} -returnCodes {1} test BadSSL-1.54 {upgrade} -body { badssl upgrade.badssl.com } test BadSSL-1.55 {webpack-dev-server} -body { badssl webpack-dev-server.badssl.com - } -result {handshake failed: certificate verify failed due to: unable to get local issuer certificate} -returnCodes {1} + } -result {handshake failed: certificate verify failed due to "unable to get local issuer certificate"} -returnCodes {1} test BadSSL-1.56 {wrong.host} -body { badssl wrong.host.badssl.com - } -result {handshake failed: certificate verify failed due to: Hostname mismatch} -returnCodes {1} + } -result {handshake failed: certificate verify failed due to "Hostname mismatch"} -returnCodes {1} test BadSSL-1.57 {mozilla-modern} -body { badssl mozilla-modern.badssl.com } # Cleanup ::tcltest::cleanupTests return ADDED tests/common.tcl Index: tests/common.tcl ================================================================== --- /dev/null +++ tests/common.tcl @@ -0,0 +1,22 @@ + +# Common Constraints +package require tls + +# Supported protocols +set protocols [list ssl2 ssl3 tls1 tls1.1 tls1.2 tls1.3] +foreach protocol $protocols { + ::tcltest::testConstraint $protocol 0 + ::tcltest::testConstraint !$protocol 1 +} + +foreach protocol [::tls::protocols] { + ::tcltest::testConstraint $protocol 1 + ::tcltest::testConstraint !$protocol 0 +} + +# OpenSSL version +::tcltest::testConstraint OpenSSL [string match "OpenSSL*" [::tls::version]] + +# Legacy OpenSSL v1.1.1 vs new v3.x +scan [lindex [split [::tls::version]] 1] %f version +::tcltest::testConstraint new_api [expr {$version >= 3.0}]