# Commands covered:  tls::ciphers
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#

# All rights reserved.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest
    namespace import ::tcltest::*
}

# The build dir is added as the first element of $PATH
package require tls

# One of these should == 1, depending on what type of ssl library
# tls was compiled against. (RSA BSAFE SSL-C or OpenSSL).
#
set ::tcltest::testConstraints(rsabsafe) 0
set ::tcltest::testConstraints(openssl) [string match "OpenSSL*" [tls::version]]

set ::EXPECTEDCIPHERS(rsabsafe) {
    EDH-DSS-RC4-SHA
    EDH-RSA-DES-CBC3-SHA
    EDH-DSS-DES-CBC3-SHA
    DES-CBC3-SHA
    RC4-SHA
    RC4-MD5
    EDH-RSA-DES-CBC-SHA
    EDH-DSS-DES-CBC-SHA
    DES-CBC-SHA
    EXP-EDH-DSS-DES-56-SHA
    EXP-EDH-DSS-RC4-56-SHA
    EXP-DES-56-SHA
    EXP-RC4-56-SHA
    EXP-EDH-RSA-DES-CBC-SHA
    EXP-EDH-DSS-DES-CBC-SHA
    EXP-DES-CBC-SHA
    EXP-RC2-CBC-MD5
    EXP-RC4-MD5
}

set ::EXPECTEDCIPHERS(openssl) {
    ECDHE-RSA-AES256-SHA
    DHE-PSK-AES256-CCM
    DHE-PSK-AES128-GCM-SHA256
    ECDHE-RSA-AES128-SHA256
    DHE-PSK-AES256-GCM-SHA384
    AES256-SHA256
    ECDHE-PSK-CHACHA20-POLY1305
    ECDHE-ECDSA-AES128-SHA256
    AES256-CCM
    ECDHE-RSA-AES128-GCM-SHA256
    DHE-RSA-AES256-SHA
    ECDHE-ECDSA-AES128-GCM-SHA256
    PSK-AES128-GCM-SHA256
    ECDHE-ECDSA-AES256-SHA
    ECDHE-RSA-AES256-GCM-SHA384
    ECDHE-PSK-AES256-CBC-SHA
    ECDHE-ECDSA-AES256-GCM-SHA384
    AES128-SHA
    PSK-AES256-GCM-SHA384
    PSK-AES128-CBC-SHA
    ECDHE-RSA-AES128-SHA
    AES128-GCM-SHA256
    ECDHE-PSK-AES128-CBC-SHA256
    AES256-GCM-SHA384
    TLS_AES_128_GCM_SHA256
    DHE-RSA-AES128-SHA256
    DHE-PSK-CHACHA20-POLY1305
    DHE-PSK-AES128-CCM
    TLS_AES_256_GCM_SHA384
    DHE-RSA-AES256-CCM
    DHE-RSA-AES128-GCM-SHA256
    ECDHE-ECDSA-AES256-CCM
    PSK-AES256-CCM
    DHE-RSA-AES256-GCM-SHA384
    AES128-CCM
    ECDHE-RSA-CHACHA20-POLY1305
    DHE-PSK-AES256-CBC-SHA
    DHE-RSA-AES128-SHA
    ECDHE-ECDSA-CHACHA20-POLY1305
    PSK-CHACHA20-POLY1305
    DHE-PSK-AES128-CBC-SHA256
    ECDHE-ECDSA-AES128-SHA
    ECDHE-PSK-AES128-CBC-SHA
    AES128-SHA256
    PSK-AES128-CBC-SHA256
    DHE-RSA-CHACHA20-POLY1305
    DHE-RSA-AES128-CCM
    DHE-RSA-AES256-SHA256
    ECDHE-ECDSA-AES128-CCM
    PSK-AES128-CCM
    TLS_CHACHA20_POLY1305_SHA256
    DHE-PSK-AES128-CBC-SHA
    AES256-SHA
    PSK-AES256-CBC-SHA
}

set ::EXPECTEDCIPHERS(openssl0.9.8) {
    DHE-RSA-AES256-SHA
    DHE-DSS-AES256-SHA
    AES256-SHA
    EDH-RSA-DES-CBC3-SHA
    EDH-DSS-DES-CBC3-SHA
    DES-CBC3-SHA
    DHE-RSA-AES128-SHA
    DHE-DSS-AES128-SHA
    AES128-SHA
    IDEA-CBC-SHA
    RC4-SHA
    RC4-MD5
    EDH-RSA-DES-CBC-SHA
    EDH-DSS-DES-CBC-SHA
    DES-CBC-SHA
    EXP-EDH-RSA-DES-CBC-SHA
    EXP-EDH-DSS-DES-CBC-SHA
    EXP-DES-CBC-SHA
    EXP-RC2-CBC-MD5
    EXP-RC4-MD5
}

set version ""
if {[string match "OpenSSL*" [tls::version]]} {
   regexp {OpenSSL ([\d\.]+)} [tls::version] -> version
}
if {![info exists ::EXPECTEDCIPHERS(openssl$version)]} {
    set version ""
}

proc listcompare {wants haves} {
    array set want {}
    array set have {}
    foreach item $wants { set want($item) 1 }
    foreach item $haves { set have($item) 1 }
    foreach item [lsort -dictionary [array names have]] {
	if {[info exists want($item)]} {
	    unset want($item) have($item)
	}
    }
    if {[array size want] || [array size have]} {
	return [list MISSING [array names want] UNEXPECTED [array names have]]
    }
}

test ciphers-1.1 {Tls::ciphers for ssl3} {rsabsafe} {
    # This will fail if you compiled against OpenSSL.
    # Change the constraint setting above.
    listcompare $::EXPECTEDCIPHERS(rsabsafe) [tls::ciphers ssl3]
} {}

test ciphers-1.2 {Tls::ciphers for tls1} {rsabsafe} {
    # This will fail if you compiled against OpenSSL.
    # Change the constraint setting above.
    listcompare $::EXPECTEDCIPHERS(rsabsafe) [tls::ciphers tls1]
} {}

test ciphers-1.3 {Tls::ciphers for ssl3} -constraints openssl -body {
    tls::ciphers ssl3
} -returnCodes 1 -result {protocol not supported}

# This version of the test is correct for OpenSSL only.
# An equivalent test for the RSA BSAFE SSL-C is earlier in this file.

test ciphers-1.4 {Tls::ciphers for tls1} {openssl} {
    # This will fail if you compiled against RSA bsafe or with a
    # different set of defines than the default.
    # Change the constraint setting in all.tcl
    listcompare $::EXPECTEDCIPHERS(openssl$version) [tls::ciphers tls1]
} {}


# cleanup
::tcltest::cleanupTests
return
