>From f34c78a2df585165e92cac4df34b47c3286484fe Mon Sep 17 00:00:00 2001
From: David Fifield <david () bamsoftware com>
Date: Tue, 24 Dec 2013 10:24:46 -0800
Subject: [PATCH 1/4] Pass complete host and port tables to try_protocol.

---
 scripts/ssl-enum-ciphers.nse | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/scripts/ssl-enum-ciphers.nse b/scripts/ssl-enum-ciphers.nse
index 396d561..998a65e 100644
--- a/scripts/ssl-enum-ciphers.nse
+++ b/scripts/ssl-enum-ciphers.nse
@@ -1090,7 +1090,7 @@ action = function(host, port)
 
   for name, _ in pairs(PROTOCOLS) do
     stdnse.print_debug(1, "Trying protocol %s.", name)
-    local co = stdnse.new_thread(try_protocol, host.ip, port.number, name, results)
+    local co = stdnse.new_thread(try_protocol, host, port, name, results)
     threads[co] = true
   end
 
-- 
1.8.5.1

>From 905e8158e5da0a3dfadd66409f047c7942b2193b Mon Sep 17 00:00:00 2001
From: David Fifield <david () bamsoftware com>
Date: Tue, 24 Dec 2013 10:01:02 -0800
Subject: [PATCH 2/4] Skeleton support for TLS extensions.

---
 scripts/ssl-enum-ciphers.nse | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/scripts/ssl-enum-ciphers.nse b/scripts/ssl-enum-ciphers.nse
index 998a65e..d90f9e4 100644
--- a/scripts/ssl-enum-ciphers.nse
+++ b/scripts/ssl-enum-ciphers.nse
@@ -703,6 +703,11 @@ local function record_write(type, protocol, b)
   return h .. b
 end
 
+local function protocol_has_extensions(protocol)
+  -- SSL doesn't have extensions; TLS does.
+  return PROTOCOLS[protocol] and PROTOCOLS[protocol] ~= PROTOCOLS["SSLv3"]
+end
+
 local function client_hello(t)
   local b, cipher, ciphers, compressor, compressors, h, len
 
@@ -759,6 +764,15 @@ local function client_hello(t)
   b = b .. bin.pack("C", #compressors)
   b = b .. compressors
 
+  if protocol_has_extensions(t["protocol"]) then
+    extensions = ""
+
+    if #extensions > 0 then
+      b = b .. bin.pack(">S", #extensions)
+      b = b .. extensions
+    end
+  end
+
   ------------
   -- Header --
   ------------
-- 
1.8.5.1

>From 66a7748dba452e54208a44283a7bfab092586a4f Mon Sep 17 00:00:00 2001
From: David Fifield <david () bamsoftware com>
Date: Tue, 24 Dec 2013 10:10:50 -0800
Subject: [PATCH 3/4] Send the server_name extension (SNI) in ssl-enum-ciphers.

Servers could possibly offer different ciphersuites based on the name
they are given. For example, the Apache configuration at
https://wiki.apache.org/httpd/NameBasedSSLVHosts has an SSLCipherSuite
specification inside a VirtualHost section.
---
 scripts/ssl-enum-ciphers.nse | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/scripts/ssl-enum-ciphers.nse b/scripts/ssl-enum-ciphers.nse
index d90f9e4..4facce3 100644
--- a/scripts/ssl-enum-ciphers.nse
+++ b/scripts/ssl-enum-ciphers.nse
@@ -708,6 +708,16 @@ local function protocol_has_extensions(protocol)
   return PROTOCOLS[protocol] and PROTOCOLS[protocol] ~= PROTOCOLS["SSLv3"]
 end
 
+-- RFC 6066, section 3 "Server Name Indication".
+local function server_name_extension(server_name)
+  local ext = bin.pack(">CSA", 0, #server_name, server_name)
+  -- server_name_list length.
+  ext = bin.pack(">S", #ext) .. ext
+  -- Extension type and length.
+  ext = bin.pack(">SS", 0, #ext) .. ext
+  return ext
+end
+
 local function client_hello(t)
   local b, cipher, ciphers, compressor, compressors, h, len
 
@@ -767,6 +777,10 @@ local function client_hello(t)
   if protocol_has_extensions(t["protocol"]) then
     extensions = ""
 
+    if t["server_name"] then
+      extensions = extensions .. server_name_extension(t["server_name"])
+    end
+
     if #extensions > 0 then
       b = b .. bin.pack(">S", #extensions)
       b = b .. extensions
@@ -875,6 +889,7 @@ local function find_ciphers(host, port, protocol)
     while (next(group)) do
       -- Create structure.
       t = {
+        ["server_name"] = host.targetname,
         ["ciphers"] = group,
         ["protocol"] = protocol
       }
@@ -927,6 +942,7 @@ local function find_compressors(host, port, protocol, good_cipher)
   while (next(compressors)) do
     -- Create structure.
     t = {
+      ["server_name"] = host.targetname,
       ["compressors"] = compressors,
       ["ciphers"] = {good_cipher},
       ["protocol"] = protocol
-- 
1.8.5.1

>From 99caf6187b3339b4916ff5227f477244c062bff4 Mon Sep 17 00:00:00 2001
From: David Fifield <david () bamsoftware com>
Date: Tue, 24 Dec 2013 11:07:38 -0800
Subject: [PATCH 4/4] Send the elliptic_curves and ec_point_formats extensions.

---
 scripts/ssl-enum-ciphers.nse | 84 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 84 insertions(+)

diff --git a/scripts/ssl-enum-ciphers.nse b/scripts/ssl-enum-ciphers.nse
index 4facce3..26a04e5 100644
--- a/scripts/ssl-enum-ciphers.nse
+++ b/scripts/ssl-enum-ciphers.nse
@@ -589,6 +589,44 @@ CIPHERS = {
 ["SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA"]             =  0xFEFF,
 }
 
+-- RFC 4492 section 5.1.1 "Supported Elliptic Curves Extension".
+local ELLIPTIC_CURVES = {
+  sect163k1 = 1,
+  sect163r1 = 2,
+  sect163r2 = 3,
+  sect193r1 = 4,
+  sect193r2 = 5,
+  sect233k1 = 6,
+  sect233r1 = 7,
+  sect239k1 = 8,
+  sect283k1 = 9,
+  sect283r1 = 10,
+  sect409k1 = 11,
+  sect409r1 = 12,
+  sect571k1 = 13,
+  sect571r1 = 14,
+  secp160k1 = 15,
+  secp160r1 = 16,
+  secp160r2 = 17,
+  secp192k1 = 18,
+  secp192r1 = 19,
+  secp224k1 = 20,
+  secp224r1 = 21,
+  secp256k1 = 22,
+  secp256r1 = 23,
+  secp384r1 = 24,
+  secp521r1 = 25,
+  arbitrary_explicit_prime_curves = 0xFF01,
+  arbitrary_explicit_char2_curves = 0xFF02,
+}
+
+-- RFC 4492 section 5.1.2 "Supported Point Formats Extension".
+local EC_POINT_FORMATS = {
+  uncompressed = 0,
+  ansiX962_compressed_prime = 1,
+  ansiX962_compressed_char2 = 2,
+}
+
 cipherstrength = {
   ["broken"] = 0,
   ["weak"]        = 1,
@@ -718,6 +756,42 @@ local function server_name_extension(server_name)
   return ext
 end
 
+-- RFC 4922, section 5.1 "Client Hello Extensions".
+local function elliptic_curves_extension(elliptic_curves)
+  local list = {}
+  for _, name in ipairs(elliptic_curves) do
+    list[#list+1] = bin.pack(">S", name)
+  end
+  local ext = table.concat(list)
+  -- elliptic_curve_list length.
+  ext = bin.pack(">S", #ext) .. ext
+  -- Extension type and length.
+  ext = bin.pack(">SS", 10, #ext) .. ext
+  return ext
+end
+
+-- RFC 4922, section 5.1 "Client Hello Extensions".
+local function ec_point_formats_extension(ec_point_formats)
+  local list = {}
+  for _, format in ipairs(ec_point_formats) do
+    list[#list+1] = bin.pack(">C", format)
+  end
+  local ext = table.concat(list)
+  -- ec_point_format_list length.
+  ext = bin.pack(">C", #ext) .. ext
+  -- Extension type and length.
+  ext = bin.pack(">SS", 11, #ext) .. ext
+  return ext
+end
+
+local function values(t)
+  local ret = {}
+  for _, v in pairs(t) do
+    ret[#ret+1] = v
+  end
+  return ret
+end
+
 local function client_hello(t)
   local b, cipher, ciphers, compressor, compressors, h, len
 
@@ -781,6 +855,16 @@ local function client_hello(t)
       extensions = extensions .. server_name_extension(t["server_name"])
     end
 
+    -- Claim to support every elliptic curve.
+    local elliptic_curves = values(ELLIPTIC_CURVES)
+    table.sort(elliptic_curves)
+    extensions = extensions .. elliptic_curves_extension(elliptic_curves)
+
+    -- Claim to support every EC point format.
+    local ec_point_formats = values(EC_POINT_FORMATS)
+    table.sort(ec_point_formats)
+    extensions = extensions .. ec_point_formats_extension(ec_point_formats)
+
     if #extensions > 0 then
       b = b .. bin.pack(">S", #extensions)
       b = b .. extensions
-- 
1.8.5.1

