From 2d87a0458ef0425629e9f11dbb382e2ec0089ad0 Mon Sep 17 00:00:00 2001 From: Eugene Burkov Date: Wed, 21 Apr 2021 18:50:33 +0300 Subject: [PATCH] Pull request: 2829 rm util Merge in DNS/adguard-home from 2829-finally to master Closes #2829. Squashed commit of the following: commit 22b287d5c2cbeced1b48747a1c4b6431c1052f12 Author: Eugene Burkov Date: Wed Apr 21 18:39:54 2021 +0300 util: rm --- internal/home/home.go | 5 +- internal/home/tls.go | 96 +++++++++++++++++++++++++++++++++++++ internal/util/tls.go | 107 ------------------------------------------ 3 files changed, 98 insertions(+), 110 deletions(-) delete mode 100644 internal/util/tls.go diff --git a/internal/home/home.go b/internal/home/home.go index b202d187..e9542011 100644 --- a/internal/home/home.go +++ b/internal/home/home.go @@ -30,7 +30,6 @@ import ( "github.com/AdguardTeam/AdGuardHome/internal/querylog" "github.com/AdguardTeam/AdGuardHome/internal/stats" "github.com/AdguardTeam/AdGuardHome/internal/updater" - "github.com/AdguardTeam/AdGuardHome/internal/util" "github.com/AdguardTeam/AdGuardHome/internal/version" "github.com/AdguardTeam/golibs/log" "gopkg.in/natefinch/lumberjack.v2" @@ -139,8 +138,8 @@ func setupContext(args options) { initConfig() - Context.tlsRoots = util.LoadSystemRootCAs() - Context.tlsCiphers = util.InitTLSCiphers() + Context.tlsRoots = LoadSystemRootCAs() + Context.tlsCiphers = InitTLSCiphers() Context.transport = &http.Transport{ DialContext: customDialContext, Proxy: getHTTPProxy, diff --git a/internal/home/tls.go b/internal/home/tls.go index f6173827..4ff8186d 100644 --- a/internal/home/tls.go +++ b/internal/home/tls.go @@ -15,12 +15,15 @@ import ( "io/ioutil" "net/http" "os" + "path/filepath" "reflect" + "runtime" "strings" "sync" "time" "github.com/AdguardTeam/golibs/log" + "golang.org/x/sys/cpu" ) var tlsWebHandlersRegistered = false @@ -551,3 +554,96 @@ func (t *TLSMod) registerWebHandlers() { httpRegister(http.MethodPost, "/control/tls/configure", t.handleTLSConfigure) httpRegister(http.MethodPost, "/control/tls/validate", t.handleTLSValidate) } + +// LoadSystemRootCAs tries to load root certificates from the operating system. +// It returns nil in case nothing is found so that that Go.crypto will use it's +// default algorithm to find system root CA list. +// +// See https://github.com/AdguardTeam/AdGuardHome/internal/issues/1311. +func LoadSystemRootCAs() (roots *x509.CertPool) { + // TODO(e.burkov): Use build tags instead. + if runtime.GOOS != "linux" { + return nil + } + + // Directories with the system root certificates, which aren't supported + // by Go.crypto. + dirs := []string{ + // Entware. + "/opt/etc/ssl/certs", + } + roots = x509.NewCertPool() + for _, dir := range dirs { + fis, err := ioutil.ReadDir(dir) + if errors.Is(err, os.ErrNotExist) { + continue + } + if err != nil { + log.Error("opening directory: %q: %s", dir, err) + } + + var rootsAdded bool + for _, fi := range fis { + var certData []byte + certData, err = ioutil.ReadFile(filepath.Join(dir, fi.Name())) + if err == nil && roots.AppendCertsFromPEM(certData) { + rootsAdded = true + } + } + + if rootsAdded { + return roots + } + } + + return nil +} + +// InitTLSCiphers performs the same work as initDefaultCipherSuites() from +// crypto/tls/common.go but don't uses lots of other default ciphers. +func InitTLSCiphers() (ciphers []uint16) { + // Check the cpu flags for each platform that has optimized GCM + // implementations. The worst case is when all these variables are + // false. + var ( + hasGCMAsmAMD64 = cpu.X86.HasAES && cpu.X86.HasPCLMULQDQ + hasGCMAsmARM64 = cpu.ARM64.HasAES && cpu.ARM64.HasPMULL + // Keep in sync with crypto/aes/cipher_s390x.go. + hasGCMAsmS390X = cpu.S390X.HasAES && + cpu.S390X.HasAESCBC && + cpu.S390X.HasAESCTR && + (cpu.S390X.HasGHASH || cpu.S390X.HasAESGCM) + + hasGCMAsm = hasGCMAsmAMD64 || hasGCMAsmARM64 || hasGCMAsmS390X + ) + + if hasGCMAsm { + // If AES-GCM hardware is provided then prioritize AES-GCM + // cipher suites. + ciphers = []uint16{ + tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, + tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, + } + } else { + // Without AES-GCM hardware, we put the ChaCha20-Poly1305 cipher + // suites first. + ciphers = []uint16{ + tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, + tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, + tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + } + } + + return append( + ciphers, + tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, + tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, + ) +} diff --git a/internal/util/tls.go b/internal/util/tls.go deleted file mode 100644 index f7498d72..00000000 --- a/internal/util/tls.go +++ /dev/null @@ -1,107 +0,0 @@ -// Package util contains various utilities. -// -// TODO(a.garipov): Such packages are widely considered an antipattern. Remove -// this when we refactor our project structure. -package util - -import ( - "crypto/tls" - "crypto/x509" - "errors" - "io/ioutil" - "os" - "runtime" - - "github.com/AdguardTeam/golibs/log" - "golang.org/x/sys/cpu" -) - -// LoadSystemRootCAs - load root CAs from the system -// Return the x509 certificate pool object -// Return nil if nothing has been found. -// This means that Go.crypto will use its default algorithm to find system root CA list. -// https://github.com/AdguardTeam/AdGuardHome/internal/issues/1311 -func LoadSystemRootCAs() *x509.CertPool { - if runtime.GOOS != "linux" { - return nil - } - - // Directories with the system root certificates, that aren't supported by Go.crypto - dirs := []string{ - "/opt/etc/ssl/certs", // Entware - } - roots := x509.NewCertPool() - for _, dir := range dirs { - fis, err := ioutil.ReadDir(dir) - if err != nil { - if !errors.Is(err, os.ErrNotExist) { - log.Error("opening directory: %q: %s", dir, err) - } - - continue - } - - rootsAdded := false - for _, fi := range fis { - var certData []byte - certData, err = ioutil.ReadFile(dir + "/" + fi.Name()) - if err == nil && roots.AppendCertsFromPEM(certData) { - rootsAdded = true - } - } - - if rootsAdded { - return roots - } - } - - return nil -} - -// InitTLSCiphers - the same as initDefaultCipherSuites() from src/crypto/tls/common.go -// but with the difference that we don't use so many other default ciphers. -func InitTLSCiphers() []uint16 { - var ciphers []uint16 - - // Check the cpu flags for each platform that has optimized GCM implementations. - // Worst case, these variables will just all be false. - var ( - hasGCMAsmAMD64 = cpu.X86.HasAES && cpu.X86.HasPCLMULQDQ - hasGCMAsmARM64 = cpu.ARM64.HasAES && cpu.ARM64.HasPMULL - // Keep in sync with crypto/aes/cipher_s390x.go. - hasGCMAsmS390X = cpu.S390X.HasAES && cpu.S390X.HasAESCBC && cpu.S390X.HasAESCTR && (cpu.S390X.HasGHASH || cpu.S390X.HasAESGCM) - - hasGCMAsm = hasGCMAsmAMD64 || hasGCMAsmARM64 || hasGCMAsmS390X - ) - - if hasGCMAsm { - // If AES-GCM hardware is provided then prioritise AES-GCM - // cipher suites. - ciphers = []uint16{ - tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, - tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, - tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, - tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, - tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, - } - } else { - // Without AES-GCM hardware, we put the ChaCha20-Poly1305 - // cipher suites first. - ciphers = []uint16{ - tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, - tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, - tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, - tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, - tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, - } - } - - otherCiphers := []uint16{ - tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, - tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, - } - ciphers = append(ciphers, otherCiphers...) - return ciphers -}