Mercurial > prosody-hg
comparison util/tlsref.lua @ 14221:565debd9c37a
Merge 13.0->trunk
| author | Matthew Wild <mwild1@gmail.com> |
|---|---|
| date | Fri, 12 Jun 2026 13:05:10 +0100 |
| parents | 926f25af2ffe |
| children | ad7f7b5f4792 |
comparison
equal
deleted
inserted
replaced
| 14216:2ec517d8d43e | 14221:565debd9c37a |
|---|---|
| 1 local array = require "prosody.util.array"; | |
| 2 local it = require "prosody.util.iterators"; | |
| 3 local version_compare = require "prosody.util.human.io".simple_version_compare; | |
| 4 | |
| 5 local latest_version = "6.0" | |
| 6 local default_version = "5.7"; | |
| 7 local default_profile = "intermediate"; -- should exist in all profiles | |
| 8 | |
| 9 -- https://datatracker.ietf.org/doc/html/rfc7919#appendix-A.1 | |
| 10 local ffdhe2048 = [[ | |
| 11 -----BEGIN DH PARAMETERS----- | |
| 12 MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz | |
| 13 +8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a | |
| 14 87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7 | |
| 15 YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi | |
| 16 7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD | |
| 17 ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg== | |
| 18 -----END DH PARAMETERS----- | |
| 19 ]]; | |
| 20 | |
| 21 local profiles = { | |
| 22 -- https://wiki.mozilla.org/Security/Server_Side_TLS | |
| 23 ["6.0"] = { | |
| 24 -- Version 6.0 as of 2026-04-08 | |
| 25 modern = { | |
| 26 protocol = "tlsv1_3"; | |
| 27 options = { cipher_server_preference = false }; | |
| 28 ciphers = "DEFAULT"; -- TLS 1.3 uses 'ciphersuites' rather than these | |
| 29 curveslist = { "X25519MLKEM768"; "X25519"; "prime256v1"; "secp384r1" }; | |
| 30 ciphersuites = { "TLS_AES_128_GCM_SHA256"; "TLS_AES_256_GCM_SHA384"; "TLS_CHACHA20_POLY1305_SHA256" }; | |
| 31 }; | |
| 32 intermediate = { | |
| 33 protocol = "tlsv1_2+"; | |
| 34 dhparam = ffdhe2048; | |
| 35 options = { cipher_server_preference = false }; | |
| 36 ciphers = { | |
| 37 "ECDHE-ECDSA-AES128-GCM-SHA256"; | |
| 38 "ECDHE-RSA-AES128-GCM-SHA256"; | |
| 39 "ECDHE-ECDSA-AES256-GCM-SHA384"; | |
| 40 "ECDHE-RSA-AES256-GCM-SHA384"; | |
| 41 "ECDHE-ECDSA-CHACHA20-POLY1305"; | |
| 42 "ECDHE-RSA-CHACHA20-POLY1305"; | |
| 43 }; | |
| 44 curveslist = { "X25519MLKEM768"; "X25519"; "prime256v1"; "secp384r1" }; | |
| 45 ciphersuites = { "TLS_AES_128_GCM_SHA256"; "TLS_AES_256_GCM_SHA384"; "TLS_CHACHA20_POLY1305_SHA256" }; | |
| 46 }; | |
| 47 }; | |
| 48 | |
| 49 ["5.8"] = { | |
| 50 -- Version 5.8 as of 2026-04-08 | |
| 51 modern = { | |
| 52 protocol = "tlsv1_3"; | |
| 53 options = { cipher_server_preference = false }; | |
| 54 ciphers = "DEFAULT"; -- TLS 1.3 uses 'ciphersuites' rather than these | |
| 55 curveslist = { "X25519MLKEM768"; "X25519"; "prime256v1"; "secp384r1" }; | |
| 56 ciphersuites = { "TLS_AES_128_GCM_SHA256"; "TLS_AES_256_GCM_SHA384"; "TLS_CHACHA20_POLY1305_SHA256" }; | |
| 57 }; | |
| 58 intermediate = { | |
| 59 protocol = "tlsv1_2+"; | |
| 60 dhparam = ffdhe2048; | |
| 61 options = { cipher_server_preference = false }; | |
| 62 ciphers = { | |
| 63 "ECDHE-ECDSA-AES128-GCM-SHA256"; | |
| 64 "ECDHE-RSA-AES128-GCM-SHA256"; | |
| 65 "ECDHE-ECDSA-AES256-GCM-SHA384"; | |
| 66 "ECDHE-RSA-AES256-GCM-SHA384"; | |
| 67 "ECDHE-ECDSA-CHACHA20-POLY1305"; | |
| 68 "ECDHE-RSA-CHACHA20-POLY1305"; | |
| 69 }; | |
| 70 curveslist = { "X25519MLKEM768"; "X25519"; "prime256v1"; "secp384r1" }; | |
| 71 ciphersuites = { "TLS_AES_128_GCM_SHA256"; "TLS_AES_256_GCM_SHA384"; "TLS_CHACHA20_POLY1305_SHA256" }; | |
| 72 }; | |
| 73 old = { | |
| 74 protocol = "tlsv1+"; | |
| 75 dhparam = ffdhe2048; | |
| 76 options = { cipher_server_preference = true }; | |
| 77 ciphers = { | |
| 78 "ECDHE-ECDSA-AES128-GCM-SHA256"; | |
| 79 "ECDHE-RSA-AES128-GCM-SHA256"; | |
| 80 "ECDHE-ECDSA-AES256-GCM-SHA384"; | |
| 81 "ECDHE-RSA-AES256-GCM-SHA384"; | |
| 82 "ECDHE-ECDSA-CHACHA20-POLY1305"; | |
| 83 "ECDHE-RSA-CHACHA20-POLY1305"; | |
| 84 "ECDHE-ECDSA-AES128-SHA256"; | |
| 85 "ECDHE-RSA-AES128-SHA256"; | |
| 86 "ECDHE-ECDSA-AES128-SHA"; | |
| 87 "ECDHE-RSA-AES128-SHA"; | |
| 88 "ECDHE-ECDSA-AES256-SHA384"; | |
| 89 "ECDHE-RSA-AES256-SHA384"; | |
| 90 "ECDHE-ECDSA-AES256-SHA"; | |
| 91 "ECDHE-RSA-AES256-SHA"; | |
| 92 "AES128-GCM-SHA256"; | |
| 93 "AES256-GCM-SHA384"; | |
| 94 "AES128-SHA256"; | |
| 95 "AES256-SHA256"; | |
| 96 "AES128-SHA"; | |
| 97 "AES256-SHA"; | |
| 98 "DES-CBC3-SHA"; | |
| 99 }; | |
| 100 curveslist = { "X25519MLKEM768"; "X25519"; "prime256v1"; "secp384r1" }; | |
| 101 ciphersuites = { "TLS_AES_128_GCM_SHA256"; "TLS_AES_256_GCM_SHA384"; "TLS_CHACHA20_POLY1305_SHA256" }; | |
| 102 }; | |
| 103 }; | |
| 104 | |
| 105 ["5.7"] = { | |
| 106 -- Version 5.7 as of 2023-07-09 | |
| 107 modern = { | |
| 108 protocol = "tlsv1_3"; | |
| 109 options = { cipher_server_preference = false }; | |
| 110 ciphers = "DEFAULT"; -- TLS 1.3 uses 'ciphersuites' rather than these | |
| 111 curveslist = { "X25519"; "prime256v1"; "secp384r1" }; | |
| 112 ciphersuites = { "TLS_AES_128_GCM_SHA256"; "TLS_AES_256_GCM_SHA384"; "TLS_CHACHA20_POLY1305_SHA256" }; | |
| 113 }; | |
| 114 intermediate = { | |
| 115 protocol = "tlsv1_2+"; | |
| 116 dhparam = ffdhe2048; | |
| 117 options = { cipher_server_preference = false }; | |
| 118 ciphers = { | |
| 119 "ECDHE-ECDSA-AES128-GCM-SHA256"; | |
| 120 "ECDHE-RSA-AES128-GCM-SHA256"; | |
| 121 "ECDHE-ECDSA-AES256-GCM-SHA384"; | |
| 122 "ECDHE-RSA-AES256-GCM-SHA384"; | |
| 123 "ECDHE-ECDSA-CHACHA20-POLY1305"; | |
| 124 "ECDHE-RSA-CHACHA20-POLY1305"; | |
| 125 "DHE-RSA-AES128-GCM-SHA256"; | |
| 126 "DHE-RSA-AES256-GCM-SHA384"; | |
| 127 "DHE-RSA-CHACHA20-POLY1305"; | |
| 128 }; | |
| 129 curveslist = { "X25519"; "prime256v1"; "secp384r1" }; | |
| 130 ciphersuites = { "TLS_AES_128_GCM_SHA256"; "TLS_AES_256_GCM_SHA384"; "TLS_CHACHA20_POLY1305_SHA256" }; | |
| 131 }; | |
| 132 old = { | |
| 133 protocol = "tlsv1+"; | |
| 134 dhparam = nil; -- openssl dhparam 1024 | |
| 135 options = { cipher_server_preference = true }; | |
| 136 ciphers = { | |
| 137 "ECDHE-ECDSA-AES128-GCM-SHA256"; | |
| 138 "ECDHE-RSA-AES128-GCM-SHA256"; | |
| 139 "ECDHE-ECDSA-AES256-GCM-SHA384"; | |
| 140 "ECDHE-RSA-AES256-GCM-SHA384"; | |
| 141 "ECDHE-ECDSA-CHACHA20-POLY1305"; | |
| 142 "ECDHE-RSA-CHACHA20-POLY1305"; | |
| 143 "DHE-RSA-AES128-GCM-SHA256"; | |
| 144 "DHE-RSA-AES256-GCM-SHA384"; | |
| 145 "DHE-RSA-CHACHA20-POLY1305"; | |
| 146 "ECDHE-ECDSA-AES128-SHA256"; | |
| 147 "ECDHE-RSA-AES128-SHA256"; | |
| 148 "ECDHE-ECDSA-AES128-SHA"; | |
| 149 "ECDHE-RSA-AES128-SHA"; | |
| 150 "ECDHE-ECDSA-AES256-SHA384"; | |
| 151 "ECDHE-RSA-AES256-SHA384"; | |
| 152 "ECDHE-ECDSA-AES256-SHA"; | |
| 153 "ECDHE-RSA-AES256-SHA"; | |
| 154 "DHE-RSA-AES128-SHA256"; | |
| 155 "DHE-RSA-AES256-SHA256"; | |
| 156 "AES128-GCM-SHA256"; | |
| 157 "AES256-GCM-SHA384"; | |
| 158 "AES128-SHA256"; | |
| 159 "AES256-SHA256"; | |
| 160 "AES128-SHA"; | |
| 161 "AES256-SHA"; | |
| 162 "DES-CBC3-SHA"; | |
| 163 }; | |
| 164 curveslist = { "X25519"; "prime256v1"; "secp384r1" }; | |
| 165 ciphersuites = { "TLS_AES_128_GCM_SHA256"; "TLS_AES_256_GCM_SHA384"; "TLS_CHACHA20_POLY1305_SHA256" }; | |
| 166 }; | |
| 167 }; | |
| 168 }; | |
| 169 | |
| 170 local function get_valid_versions() | |
| 171 return array.collect(it.keys(profiles)):sort(version_compare):reverse(); | |
| 172 end | |
| 173 | |
| 174 local pref_order = { modern = 100, intermediate = 50, old = 0 }; | |
| 175 | |
| 176 local function sort_profile_by_pref(a, b) | |
| 177 local pref_a, pref_b = pref_order[a] or 0, pref_order[b] or 0; | |
| 178 return pref_a > pref_b; -- Best first | |
| 179 end | |
| 180 | |
| 181 local function get_valid_profile_names(version) | |
| 182 if version == "latest" then | |
| 183 version = latest_version; | |
| 184 end | |
| 185 local version_profiles = profiles[version or default_version]; | |
| 186 if not version_profiles then | |
| 187 return nil, "unknown-version"; | |
| 188 end | |
| 189 return array.collect(it.keys(version_profiles)):sort(sort_profile_by_pref); | |
| 190 end | |
| 191 | |
| 192 local function get_profile(version, profile_name) | |
| 193 if version == "latest" then | |
| 194 version = latest_version; | |
| 195 end | |
| 196 local version_profiles = profiles[version or default_version]; | |
| 197 if not version_profiles then | |
| 198 return nil, "unknown-version"; | |
| 199 end | |
| 200 local profile = version_profiles[profile_name or default_profile]; | |
| 201 if not profile then | |
| 202 return nil, "unknown-profile"; | |
| 203 end | |
| 204 return profile; | |
| 205 end | |
| 206 | |
| 207 local function get_default_version() | |
| 208 return default_version; | |
| 209 end | |
| 210 | |
| 211 local function get_latest_version() | |
| 212 return latest_version; | |
| 213 end | |
| 214 | |
| 215 local function get_default_profile_name(version) | |
| 216 -- Default profile name is currently the same across all versions, | |
| 217 -- but can't guarantee this in the future - ensure valid version | |
| 218 if version ~= "latest" and not profiles[version or default_version] then | |
| 219 return nil, "unknown-version"; | |
| 220 end | |
| 221 return default_profile; | |
| 222 end | |
| 223 | |
| 224 return { | |
| 225 profiles = profiles; | |
| 226 get_default_version = get_default_version; | |
| 227 get_latest_version = get_latest_version; | |
| 228 get_default_profile_name = get_default_profile_name; | |
| 229 get_valid_versions = get_valid_versions; | |
| 230 get_valid_profile_names = get_valid_profile_names; | |
| 231 get_profile = get_profile; | |
| 232 }; |
