mirror of
https://github.com/caddyserver/caddy.git
synced 2024-11-29 12:16:16 +08:00
0a95b5d359
Breaking API change for server type plugins that use caddytls package. Now an error value is returned from NewConfig as well. Sorry about that.
549 lines
18 KiB
Go
549 lines
18 KiB
Go
// Copyright 2015 Light Code Labs, LLC
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package caddytls
|
|
|
|
import (
|
|
"crypto/tls"
|
|
"crypto/x509"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"sync/atomic"
|
|
|
|
"github.com/xenolf/lego/challenge/tlsalpn01"
|
|
|
|
"github.com/klauspost/cpuid"
|
|
"github.com/mholt/caddy"
|
|
"github.com/mholt/certmagic"
|
|
"github.com/xenolf/lego/certcrypto"
|
|
)
|
|
|
|
// Config describes how TLS should be configured and used.
|
|
type Config struct {
|
|
// The hostname or class of hostnames this config is
|
|
// designated for; can contain wildcard characters
|
|
// according to RFC 6125 §6.4.3 - this field MUST
|
|
// be set in order for things to work as expected,
|
|
// must be normalized, and if an IP address, must
|
|
// be normalized
|
|
Hostname string
|
|
|
|
// Whether TLS is enabled
|
|
Enabled bool
|
|
|
|
// Minimum and maximum protocol versions to allow
|
|
ProtocolMinVersion uint16
|
|
ProtocolMaxVersion uint16
|
|
|
|
// The list of cipher suites; first should be
|
|
// TLS_FALLBACK_SCSV to prevent degrade attacks
|
|
Ciphers []uint16
|
|
|
|
// Whether to prefer server cipher suites
|
|
PreferServerCipherSuites bool
|
|
|
|
// The list of preferred curves
|
|
CurvePreferences []tls.CurveID
|
|
|
|
// Client authentication policy
|
|
ClientAuth tls.ClientAuthType
|
|
|
|
// List of client CA certificates to allow, if
|
|
// client authentication is enabled
|
|
ClientCerts []string
|
|
|
|
// Manual means user provides own certs and keys
|
|
Manual bool
|
|
|
|
// Managed means this config should be managed
|
|
// by the CertMagic Config (Manager field)
|
|
Managed bool
|
|
|
|
// Manager is how certificates are managed
|
|
Manager *certmagic.Config
|
|
|
|
// SelfSigned means that this hostname is
|
|
// served with a self-signed certificate
|
|
// that we generated in memory for convenience
|
|
SelfSigned bool
|
|
|
|
// The email address to use when creating or
|
|
// using an ACME account (fun fact: if this
|
|
// is set to "off" then this config will not
|
|
// qualify for managed TLS)
|
|
ACMEEmail string
|
|
|
|
// The list of protocols to choose from for Application Layer
|
|
// Protocol Negotiation (ALPN).
|
|
ALPN []string
|
|
|
|
// The final tls.Config created with
|
|
// buildStandardTLSConfig()
|
|
tlsConfig *tls.Config
|
|
}
|
|
|
|
// NewConfig returns a new Config with a pointer to the instance's
|
|
// certificate cache. You will usually need to set other fields on
|
|
// the returned Config for successful practical use.
|
|
func NewConfig(inst *caddy.Instance) (*Config, error) {
|
|
inst.StorageMu.RLock()
|
|
certCache, ok := inst.Storage[CertCacheInstStorageKey].(*certmagic.Cache)
|
|
inst.StorageMu.RUnlock()
|
|
if !ok || certCache == nil {
|
|
// set up the clustering plugin, if there is one (and there should always
|
|
// be one since this tls plugin requires it) -- this should be done exactly
|
|
// once, but we can't do it during init while plugins are still registering,
|
|
// so do it as soon as we run a setup)
|
|
if atomic.CompareAndSwapInt32(&clusterPluginSetup, 0, 1) {
|
|
clusterPluginName := os.Getenv("CADDY_CLUSTERING")
|
|
if clusterPluginName == "" {
|
|
clusterPluginName = "file" // name of default storage plugin
|
|
}
|
|
clusterFn, ok := clusterProviders[clusterPluginName]
|
|
if ok {
|
|
storage, err := clusterFn()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("constructing cluster plugin %s: %v", clusterPluginName, err)
|
|
}
|
|
certmagic.DefaultStorage = storage
|
|
} else {
|
|
return nil, fmt.Errorf("unrecognized cluster plugin (was it included in the Caddy build?): %s", clusterPluginName)
|
|
}
|
|
}
|
|
certCache = certmagic.NewCache(certmagic.DefaultStorage)
|
|
inst.OnShutdown = append(inst.OnShutdown, func() error {
|
|
certCache.Stop()
|
|
return nil
|
|
})
|
|
inst.StorageMu.Lock()
|
|
inst.Storage[CertCacheInstStorageKey] = certCache
|
|
inst.StorageMu.Unlock()
|
|
}
|
|
return &Config{
|
|
Manager: certmagic.NewWithCache(certCache, certmagic.Config{}),
|
|
}, nil
|
|
}
|
|
|
|
// buildStandardTLSConfig converts cfg (*caddytls.Config) to a *tls.Config
|
|
// and stores it in cfg so it can be used in servers. If TLS is disabled,
|
|
// no tls.Config is created.
|
|
func (c *Config) buildStandardTLSConfig() error {
|
|
if !c.Enabled {
|
|
return nil
|
|
}
|
|
|
|
config := new(tls.Config)
|
|
|
|
ciphersAdded := make(map[uint16]struct{})
|
|
curvesAdded := make(map[tls.CurveID]struct{})
|
|
|
|
// add cipher suites
|
|
for _, ciph := range c.Ciphers {
|
|
if _, ok := ciphersAdded[ciph]; !ok {
|
|
ciphersAdded[ciph] = struct{}{}
|
|
config.CipherSuites = append(config.CipherSuites, ciph)
|
|
}
|
|
}
|
|
|
|
config.PreferServerCipherSuites = c.PreferServerCipherSuites
|
|
|
|
// add curve preferences
|
|
for _, curv := range c.CurvePreferences {
|
|
if _, ok := curvesAdded[curv]; !ok {
|
|
curvesAdded[curv] = struct{}{}
|
|
config.CurvePreferences = append(config.CurvePreferences, curv)
|
|
}
|
|
}
|
|
|
|
// ensure ALPN includes the ACME TLS-ALPN protocol
|
|
var alpnFound bool
|
|
for _, a := range c.ALPN {
|
|
if a == tlsalpn01.ACMETLS1Protocol {
|
|
alpnFound = true
|
|
break
|
|
}
|
|
}
|
|
if !alpnFound {
|
|
c.ALPN = append(c.ALPN, tlsalpn01.ACMETLS1Protocol)
|
|
}
|
|
|
|
config.MinVersion = c.ProtocolMinVersion
|
|
config.MaxVersion = c.ProtocolMaxVersion
|
|
config.ClientAuth = c.ClientAuth
|
|
config.NextProtos = c.ALPN
|
|
config.GetCertificate = c.Manager.GetCertificate
|
|
|
|
// set up client authentication if enabled
|
|
if config.ClientAuth != tls.NoClientCert {
|
|
pool := x509.NewCertPool()
|
|
clientCertsAdded := make(map[string]struct{})
|
|
|
|
for _, caFile := range c.ClientCerts {
|
|
// don't add cert to pool more than once
|
|
if _, ok := clientCertsAdded[caFile]; ok {
|
|
continue
|
|
}
|
|
clientCertsAdded[caFile] = struct{}{}
|
|
|
|
// Any client with a certificate from this CA will be allowed to connect
|
|
caCrt, err := ioutil.ReadFile(caFile)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if !pool.AppendCertsFromPEM(caCrt) {
|
|
return fmt.Errorf("error loading client certificate '%s': no certificates were successfully parsed", caFile)
|
|
}
|
|
}
|
|
|
|
config.ClientCAs = pool
|
|
}
|
|
|
|
// default cipher suites
|
|
if len(config.CipherSuites) == 0 {
|
|
config.CipherSuites = getPreferredDefaultCiphers()
|
|
}
|
|
|
|
// for security, ensure TLS_FALLBACK_SCSV is always included first
|
|
if len(config.CipherSuites) == 0 || config.CipherSuites[0] != tls.TLS_FALLBACK_SCSV {
|
|
config.CipherSuites = append([]uint16{tls.TLS_FALLBACK_SCSV}, config.CipherSuites...)
|
|
}
|
|
|
|
// store the resulting new tls.Config
|
|
c.tlsConfig = config
|
|
|
|
return nil
|
|
}
|
|
|
|
// MakeTLSConfig makes a tls.Config from configs. The returned
|
|
// tls.Config is programmed to load the matching caddytls.Config
|
|
// based on the hostname in SNI, but that's all. This is used
|
|
// to create a single TLS configuration for a listener (a group
|
|
// of sites).
|
|
func MakeTLSConfig(configs []*Config) (*tls.Config, error) {
|
|
if len(configs) == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
configMap := make(configGroup)
|
|
|
|
for i, cfg := range configs {
|
|
if cfg == nil {
|
|
// avoid nil pointer dereference below this loop
|
|
configs[i] = new(Config)
|
|
continue
|
|
}
|
|
|
|
// can't serve TLS and non-TLS on same port
|
|
if i > 0 && cfg.Enabled != configs[i-1].Enabled {
|
|
thisConfProto, lastConfProto := "not TLS", "not TLS"
|
|
if cfg.Enabled {
|
|
thisConfProto = "TLS"
|
|
}
|
|
if configs[i-1].Enabled {
|
|
lastConfProto = "TLS"
|
|
}
|
|
return nil, fmt.Errorf("cannot multiplex %s (%s) and %s (%s) on same listener",
|
|
configs[i-1].Hostname, lastConfProto, cfg.Hostname, thisConfProto)
|
|
}
|
|
|
|
// convert this caddytls.Config into a tls.Config
|
|
if err := cfg.buildStandardTLSConfig(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// if an existing config with this hostname was already
|
|
// configured, then they must be identical (or at least
|
|
// compatible), otherwise that is a configuration error
|
|
if otherConfig, ok := configMap[cfg.Hostname]; ok {
|
|
if err := assertConfigsCompatible(cfg, otherConfig); err != nil {
|
|
return nil, fmt.Errorf("incompatible TLS configurations for the same SNI "+
|
|
"name (%s) on the same listener: %v",
|
|
cfg.Hostname, err)
|
|
}
|
|
}
|
|
|
|
// key this config by its hostname (overwrites
|
|
// configs with the same hostname pattern; should
|
|
// be OK since we already asserted they are roughly
|
|
// the same); during TLS handshakes, configs are
|
|
// loaded based on the hostname pattern according
|
|
// to client's ServerName (SNI) value
|
|
if cfg.Hostname == "0.0.0.0" || cfg.Hostname == "::" {
|
|
configMap[""] = cfg
|
|
} else {
|
|
configMap[cfg.Hostname] = cfg
|
|
}
|
|
}
|
|
|
|
// Is TLS disabled? By now, we know that all
|
|
// configs agree whether it is or not, so we
|
|
// can just look at the first one. If so,
|
|
// we're done here.
|
|
if len(configs) == 0 || !configs[0].Enabled {
|
|
return nil, nil
|
|
}
|
|
|
|
return &tls.Config{
|
|
// A tls.Config must have Certificates or GetCertificate
|
|
// set, in order to be accepted by tls.Listen and quic.Listen.
|
|
// TODO: remove this once the standard library allows a tls.Config with
|
|
// only GetConfigForClient set. https://github.com/mholt/caddy/pull/2404
|
|
GetCertificate: func(*tls.ClientHelloInfo) (*tls.Certificate, error) {
|
|
return nil, fmt.Errorf("all certificates configured via GetConfigForClient")
|
|
},
|
|
GetConfigForClient: configMap.GetConfigForClient,
|
|
}, nil
|
|
}
|
|
|
|
// assertConfigsCompatible returns an error if the two Configs
|
|
// do not have the same (or roughly compatible) configurations.
|
|
// If one of the tlsConfig pointers on either Config is nil,
|
|
// an error will be returned. If both are nil, no error.
|
|
func assertConfigsCompatible(cfg1, cfg2 *Config) error {
|
|
c1, c2 := cfg1.tlsConfig, cfg2.tlsConfig
|
|
|
|
if (c1 == nil && c2 != nil) || (c1 != nil && c2 == nil) {
|
|
return fmt.Errorf("one config is not made")
|
|
}
|
|
if c1 == nil && c2 == nil {
|
|
return nil
|
|
}
|
|
|
|
if len(c1.CipherSuites) != len(c2.CipherSuites) {
|
|
return fmt.Errorf("different number of allowed cipher suites")
|
|
}
|
|
for i, ciph := range c1.CipherSuites {
|
|
if c2.CipherSuites[i] != ciph {
|
|
return fmt.Errorf("different cipher suites or different order")
|
|
}
|
|
}
|
|
|
|
if len(c1.CurvePreferences) != len(c2.CurvePreferences) {
|
|
return fmt.Errorf("different number of allowed cipher suites")
|
|
}
|
|
for i, curve := range c1.CurvePreferences {
|
|
if c2.CurvePreferences[i] != curve {
|
|
return fmt.Errorf("different curve preferences or different order")
|
|
}
|
|
}
|
|
|
|
if len(c1.NextProtos) != len(c2.NextProtos) {
|
|
return fmt.Errorf("different number of ALPN (NextProtos) values")
|
|
}
|
|
for i, proto := range c1.NextProtos {
|
|
if c2.NextProtos[i] != proto {
|
|
return fmt.Errorf("different ALPN (NextProtos) values or different order")
|
|
}
|
|
}
|
|
|
|
if c1.PreferServerCipherSuites != c2.PreferServerCipherSuites {
|
|
return fmt.Errorf("one prefers server cipher suites, the other does not")
|
|
}
|
|
if c1.MinVersion != c2.MinVersion {
|
|
return fmt.Errorf("minimum TLS version mismatch")
|
|
}
|
|
if c1.MaxVersion != c2.MaxVersion {
|
|
return fmt.Errorf("maximum TLS version mismatch")
|
|
}
|
|
if c1.ClientAuth != c2.ClientAuth {
|
|
return fmt.Errorf("client authentication policy mismatch")
|
|
}
|
|
if c1.ClientAuth != tls.NoClientCert && c2.ClientAuth != tls.NoClientCert && c1.ClientCAs != c2.ClientCAs {
|
|
// Two hosts defined on the same listener are not compatible if they
|
|
// have ClientAuth enabled, because there's no guarantee beyond the
|
|
// hostname which config will be used (because SNI only has server name).
|
|
// To prevent clients from bypassing authentication, require that
|
|
// ClientAuth be configured in an unambiguous manner.
|
|
return fmt.Errorf("multiple hosts requiring client authentication ambiguously configured")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// ConfigGetter gets a Config keyed by key.
|
|
type ConfigGetter func(c *caddy.Controller) *Config
|
|
|
|
var configGetters = make(map[string]ConfigGetter)
|
|
|
|
// RegisterConfigGetter registers fn as the way to get a
|
|
// Config for server type serverType.
|
|
func RegisterConfigGetter(serverType string, fn ConfigGetter) {
|
|
configGetters[serverType] = fn
|
|
}
|
|
|
|
// SetDefaultTLSParams sets the default TLS cipher suites, protocol versions,
|
|
// and server preferences of a server.Config if they were not previously set
|
|
// (it does not overwrite; only fills in missing values).
|
|
func SetDefaultTLSParams(config *Config) {
|
|
// If no ciphers provided, use default list
|
|
if len(config.Ciphers) == 0 {
|
|
config.Ciphers = getPreferredDefaultCiphers()
|
|
}
|
|
|
|
// Not a cipher suite, but still important for mitigating protocol downgrade attacks
|
|
// (prepend since having it at end breaks http2 due to non-h2-approved suites before it)
|
|
config.Ciphers = append([]uint16{tls.TLS_FALLBACK_SCSV}, config.Ciphers...)
|
|
|
|
// If no curves provided, use default list
|
|
if len(config.CurvePreferences) == 0 {
|
|
config.CurvePreferences = defaultCurves
|
|
}
|
|
|
|
// Set default protocol min and max versions - must balance compatibility and security
|
|
if config.ProtocolMinVersion == 0 {
|
|
config.ProtocolMinVersion = tls.VersionTLS12
|
|
}
|
|
if config.ProtocolMaxVersion == 0 {
|
|
config.ProtocolMaxVersion = tls.VersionTLS12
|
|
}
|
|
|
|
// Prefer server cipher suites
|
|
config.PreferServerCipherSuites = true
|
|
}
|
|
|
|
// Map of supported key types
|
|
var supportedKeyTypes = map[string]certcrypto.KeyType{
|
|
"P384": certcrypto.EC384,
|
|
"P256": certcrypto.EC256,
|
|
"RSA8192": certcrypto.RSA8192,
|
|
"RSA4096": certcrypto.RSA4096,
|
|
"RSA2048": certcrypto.RSA2048,
|
|
}
|
|
|
|
// SupportedProtocols is a map of supported protocols.
|
|
// HTTP/2 only supports TLS 1.2 and higher.
|
|
// If updating this map, also update tlsProtocolStringToMap in caddyhttp/fastcgi/fastcgi.go
|
|
var SupportedProtocols = map[string]uint16{
|
|
"tls1.0": tls.VersionTLS10,
|
|
"tls1.1": tls.VersionTLS11,
|
|
"tls1.2": tls.VersionTLS12,
|
|
}
|
|
|
|
// GetSupportedProtocolName returns the protocol name
|
|
func GetSupportedProtocolName(protocol uint16) (string, error) {
|
|
for k, v := range SupportedProtocols {
|
|
if v == protocol {
|
|
return k, nil
|
|
}
|
|
}
|
|
|
|
return "", fmt.Errorf("name: unsupported protocol")
|
|
}
|
|
|
|
// SupportedCiphersMap has supported ciphers, used only for parsing config.
|
|
//
|
|
// Note that, at time of writing, HTTP/2 blacklists 276 cipher suites,
|
|
// including all but four of the suites below (the four GCM suites).
|
|
// See https://http2.github.io/http2-spec/#BadCipherSuites
|
|
//
|
|
// TLS_FALLBACK_SCSV is not in this list because we manually ensure
|
|
// it is always added (even though it is not technically a cipher suite).
|
|
//
|
|
// This map, like any map, is NOT ORDERED. Do not range over this map.
|
|
var SupportedCiphersMap = map[string]uint16{
|
|
"ECDHE-ECDSA-AES256-GCM-SHA384": tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
|
"ECDHE-RSA-AES256-GCM-SHA384": tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
|
"ECDHE-ECDSA-AES128-GCM-SHA256": tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
|
"ECDHE-RSA-AES128-GCM-SHA256": tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
|
"ECDHE-ECDSA-WITH-CHACHA20-POLY1305": tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
|
|
"ECDHE-RSA-WITH-CHACHA20-POLY1305": tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
|
|
"ECDHE-RSA-AES256-CBC-SHA": tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
|
"ECDHE-RSA-AES128-CBC-SHA": tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
|
"ECDHE-ECDSA-AES256-CBC-SHA": tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
|
"ECDHE-ECDSA-AES128-CBC-SHA": tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
|
"RSA-AES256-CBC-SHA": tls.TLS_RSA_WITH_AES_256_CBC_SHA,
|
|
"RSA-AES128-CBC-SHA": tls.TLS_RSA_WITH_AES_128_CBC_SHA,
|
|
"ECDHE-RSA-3DES-EDE-CBC-SHA": tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
|
"RSA-3DES-EDE-CBC-SHA": tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
|
|
}
|
|
|
|
// GetSupportedCipherName returns the cipher name
|
|
func GetSupportedCipherName(cipher uint16) (string, error) {
|
|
for k, v := range SupportedCiphersMap {
|
|
if v == cipher {
|
|
return k, nil
|
|
}
|
|
}
|
|
|
|
return "", fmt.Errorf("name: unsupported cipher")
|
|
}
|
|
|
|
// List of all the ciphers we want to use by default
|
|
var defaultCiphers = []uint16{
|
|
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
|
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
|
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
|
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
|
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
|
|
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
|
|
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
|
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
|
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
|
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
|
}
|
|
|
|
// List of ciphers we should prefer if native AESNI support is missing
|
|
var defaultCiphersNonAESNI = []uint16{
|
|
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
|
|
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
|
|
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
|
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
|
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
|
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
|
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
|
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
|
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
|
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
|
}
|
|
|
|
// getPreferredDefaultCiphers returns an appropriate cipher suite to use, depending on
|
|
// the hardware support available for AES-NI.
|
|
//
|
|
// See https://github.com/mholt/caddy/issues/1674
|
|
func getPreferredDefaultCiphers() []uint16 {
|
|
if cpuid.CPU.AesNi() {
|
|
return defaultCiphers
|
|
}
|
|
|
|
// Return a cipher suite that prefers ChaCha20
|
|
return defaultCiphersNonAESNI
|
|
}
|
|
|
|
// Map of supported curves
|
|
// https://golang.org/pkg/crypto/tls/#CurveID
|
|
var supportedCurvesMap = map[string]tls.CurveID{
|
|
"X25519": tls.X25519,
|
|
"P256": tls.CurveP256,
|
|
"P384": tls.CurveP384,
|
|
"P521": tls.CurveP521,
|
|
}
|
|
|
|
// List of all the curves we want to use by default.
|
|
//
|
|
// This list should only include curves which are fast by design (e.g. X25519)
|
|
// and those for which an optimized assembly implementation exists (e.g. P256).
|
|
// The latter ones can be found here: https://github.com/golang/go/tree/master/src/crypto/elliptic
|
|
var defaultCurves = []tls.CurveID{
|
|
tls.X25519,
|
|
tls.CurveP256,
|
|
}
|
|
|
|
var clusterPluginSetup int32 // access atomically
|
|
|
|
// CertCacheInstStorageKey is the name of the key for
|
|
// accessing the certificate storage on the *caddy.Instance.
|
|
const CertCacheInstStorageKey = "tls_cert_cache"
|