when using tls, if no pinned key is set, pin the key from the cert. require that cert keys match a pinned key

This commit is contained in:
Arceliar 2021-06-19 09:53:11 -05:00
parent 1bf751a474
commit 5564de94ba
2 changed files with 38 additions and 6 deletions

View File

@ -54,7 +54,7 @@ type TcpListener struct {
} }
type TcpUpgrade struct { type TcpUpgrade struct {
upgrade func(c net.Conn) (net.Conn, error) upgrade func(c net.Conn, o *tcpOptions) (net.Conn, error)
name string name string
} }
@ -361,7 +361,7 @@ func (t *tcp) handler(sock net.Conn, incoming bool, options tcpOptions) chan str
var upgraded bool var upgraded bool
if options.upgrade != nil { if options.upgrade != nil {
var err error var err error
if sock, err = options.upgrade.upgrade(sock); err != nil { if sock, err = options.upgrade.upgrade(sock, &options); err != nil {
t.links.core.log.Errorln("TCP handler upgrade failed:", err) t.links.core.log.Errorln("TCP handler upgrade failed:", err)
return nil return nil
} }

View File

@ -9,6 +9,7 @@ import (
"crypto/x509/pkix" "crypto/x509/pkix"
"encoding/hex" "encoding/hex"
"encoding/pem" "encoding/pem"
"errors"
"log" "log"
"math/big" "math/big"
"net" "net"
@ -76,16 +77,47 @@ func (t *tcptls) init(tcp *tcp) {
} }
} }
func (t *tcptls) upgradeListener(c net.Conn) (net.Conn, error) { func (t *tcptls) configForOptions(options *tcpOptions) *tls.Config {
conn := tls.Server(c, t.config) config := *t.config
config.VerifyPeerCertificate = func(rawCerts [][]byte, _ [][]*x509.Certificate) error {
if len(rawCerts) != 1 {
return errors.New("tls not exactly 1 cert")
}
cert, err := x509.ParseCertificate(rawCerts[0])
if err != nil {
return errors.New("tls failed to parse cert")
}
if cert.PublicKeyAlgorithm != x509.Ed25519 {
return errors.New("tls wrong cert algorithm")
}
pk := cert.PublicKey.(ed25519.PublicKey)
var key keyArray
copy(key[:], pk)
// If options does not have a pinned key, then pin one now
if options.pinnedEd25519Keys == nil {
options.pinnedEd25519Keys = make(map[keyArray]struct{})
options.pinnedEd25519Keys[key] = struct{}{}
}
if _, isIn := options.pinnedEd25519Keys[key]; !isIn {
return errors.New("tls key does not match pinned key")
}
return nil
}
return &config
}
func (t *tcptls) upgradeListener(c net.Conn, options *tcpOptions) (net.Conn, error) {
config := t.configForOptions(options)
conn := tls.Server(c, config)
if err := conn.Handshake(); err != nil { if err := conn.Handshake(); err != nil {
return c, err return c, err
} }
return conn, nil return conn, nil
} }
func (t *tcptls) upgradeDialer(c net.Conn) (net.Conn, error) { func (t *tcptls) upgradeDialer(c net.Conn, options *tcpOptions) (net.Conn, error) {
conn := tls.Client(c, t.config) config := t.configForOptions(options)
conn := tls.Client(c, config)
if err := conn.Handshake(); err != nil { if err := conn.Handshake(); err != nil {
return c, err return c, err
} }