-
Notifications
You must be signed in to change notification settings - Fork 157
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow supplying external crypto.Signer for TLS signature #524
Comments
Hiya! Thanks for raising this. I think this makes a lot of sense. I'd like to retain the "pass key directly" functionality though since that's what everyone is already using and is a very common way to use the tls library from stdlib too. But I'm happy for something like this to be added and be tried before falling back to whatever may have been passed in the config for the raw key. |
got it, yeah adding the Signer capability is what i meant (vs breaking change) fwiw, if i'm not mistaken, even the privatekeys implements Singer too so there maybe a path to converge/collapse internally
and fyi, atleast in go, the tls negotations uses |
Hey @salrashid123 could I get your help on this? I am going to start working on a new major release and want to address all API breaks. Do you have a suggested API/have any pseudo-code? |
hi- i'm not at all familiar with how the API is composed is used in practice (i just used it for a pretty odd reason) but maybe able help in other ways. i did reverse the code in the library as-is to plumb through a signer ..it just involved mashing the current lbirary allows you to pass a i did an override of the diff below are the changes i use a software tpm to save an rsa and ecc key and then get its crypto.Signer...but you can use any signer rm -rf /tmp/myvtpm
mkdir /tmp/myvtpm
sudo swtpm socket --tpmstate dir=/tmp/myvtpm --tpm2 --server type=tcp,port=2321 --ctrl type=tcp,port=2322 --flags not-need-init,startup-clear
export TPM2TOOLS_TCTI="swtpm:port=2321"
tpm2_pcrread sha256:23
## create primary
tpm2_flushcontext -t
tpm2_createprimary -C o -c primary.ctx
### ecc
tpm2_create -G ecc256:ecdsa -g sha256 -u ecc.pub -r ecc.priv -C primary.ctx
tpm2_flushcontext -t
tpm2_load -C primary.ctx -u ecc.pub -r ecc.priv -c ecc.ctx
tpm2_evictcontrol -C o -c ecc.ctx 0x81008000
tpm2_flushcontext -t
## rsassa
tpm2_create -G rsa2048:rsassa:null -g sha256 -u rsassa.pub -r rsassa.priv -C primary.ctx
tpm2_flushcontext -t
tpm2_load -C primary.ctx -u rsassa.pub -r rsassa.priv -c rsassa.ctx
tpm2_evictcontrol -C o -c rsassa.ctx 0x81008002
tpm2_flushcontext -t diff --git a/cipher_suite.go b/cipher_suite.go
index 6f7015c..11fde92 100644
--- a/cipher_suite.go
+++ b/cipher_suite.go
@@ -4,6 +4,7 @@
package dtls
import (
+ "crypto"
"crypto/ecdsa"
"crypto/ed25519"
"crypto/rsa"
@@ -264,6 +265,16 @@ func filterCipherSuitesForCertificate(cert *tls.Certificate, cipherSuites []Ciph
certType = clientcertificate.ECDSASign
case *rsa.PrivateKey:
certType = clientcertificate.RSASign
+ case crypto.Signer:
+ s := cert.PrivateKey.(crypto.Signer).Public()
+ switch s.(type) {
+ case ed25519.PublicKey:
+ certType = clientcertificate.ECDSASign
+ case *ecdsa.PublicKey:
+ certType = clientcertificate.ECDSASign
+ case *rsa.PublicKey:
+ certType = clientcertificate.RSASign
+ }
}
filtered := []CipherSuite{}
diff --git a/config.go b/config.go
index d765ecd..51ef72a 100644
--- a/config.go
+++ b/config.go
@@ -5,6 +5,7 @@ package dtls
import (
"context"
+ "crypto"
"crypto/ecdsa"
"crypto/ed25519"
"crypto/rsa"
@@ -280,6 +281,7 @@ func validateConfig(config *Config) error {
case ed25519.PrivateKey:
case *ecdsa.PrivateKey:
case *rsa.PrivateKey:
+ case crypto.Signer:
default:
return errInvalidPrivateKey
}
diff --git a/crypto.go b/crypto.go
index 7b01002..1d84e37 100644
--- a/crypto.go
+++ b/crypto.go
@@ -55,6 +55,14 @@ func generateKeySignature(clientRandom, serverRandom, publicKey []byte, namedCur
case *rsa.PrivateKey:
hashed := hashAlgorithm.Digest(msg)
return p.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash())
+ case crypto.Signer:
+ hashed := hashAlgorithm.Digest(msg)
+ // if using rsapss and TPM
+ // return p.Sign(rand.Reader, hashed, &rsa.PSSOptions{
+ // Hash: hashAlgorithm.CryptoHash(),
+ // SaltLength: rsa.PSSSaltLengthAuto,
+ // })
+ return p.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash())
}
return nil, errKeySignatureGenerateUnimplemented
@@ -93,6 +101,12 @@ func verifyKeySignature(message, remoteKeySignature []byte, hashAlgorithm hash.A
case x509.SHA1WithRSA, x509.SHA256WithRSA, x509.SHA384WithRSA, x509.SHA512WithRSA:
hashed := hashAlgorithm.Digest(message)
return rsa.VerifyPKCS1v15(p, hashAlgorithm.CryptoHash(), hashed, remoteKeySignature)
+ // case x509.SHA256WithRSAPSS:
+ // hashed := hashAlgorithm.Digest(message)
+ // //if TPM, use rsa.PSSSaltLengthAuto
+ // return rsa.VerifyPSS(p, hashAlgorithm.CryptoHash(), hashed, remoteKeySignature, &rsa.PSSOptions{
+ // SaltLength: rsa.PSSSaltLengthAuto,
+ // })
default:
return errKeySignatureVerifyUnimplemented
}
@@ -123,6 +137,11 @@ func generateCertificateVerify(handshakeBodies []byte, privateKey crypto.Private
case *ecdsa.PrivateKey:
return p.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash())
case *rsa.PrivateKey:
+ // if using rsapss and TPM
+ // return p.Sign(rand.Reader, hashed, &rsa.PSSOptions{
+ // Hash: hashAlgorithm.CryptoHash(),
+ // SaltLength: rsa.PSSSaltLengthAuto,
+ // })
return p.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash())
}
@@ -162,6 +181,12 @@ func verifyCertificateVerify(handshakeBodies []byte, hashAlgorithm hash.Algorith
case x509.SHA1WithRSA, x509.SHA256WithRSA, x509.SHA384WithRSA, x509.SHA512WithRSA:
hash := hashAlgorithm.Digest(handshakeBodies)
return rsa.VerifyPKCS1v15(p, hashAlgorithm.CryptoHash(), hash, remoteKeySignature)
+ // case x509.SHA256WithRSAPSS:
+ // hashed := hashAlgorithm.Digest(handshakeBodies)
+ // //if using rsapss and TPM
+ // return rsa.VerifyPSS(p, hashAlgorithm.CryptoHash(), hashed, remoteKeySignature, &rsa.PSSOptions{
+ // SaltLength: rsa.PSSSaltLengthAuto,
+ // })
default:
return errKeySignatureVerifyUnimplemented
}
diff --git a/examples/listen/selfsign/main.go b/examples/listen/selfsign/main.go
index 025b667..2332935 100644
--- a/examples/listen/selfsign/main.go
+++ b/examples/listen/selfsign/main.go
@@ -8,20 +8,63 @@ import (
"context"
"crypto/tls"
"fmt"
+ "io"
+ "log"
"net"
+ "slices"
"time"
+ "github.com/google/go-tpm-tools/client"
+ "github.com/google/go-tpm-tools/simulator"
+ "github.com/google/go-tpm/tpmutil"
"github.com/pion/dtls/v2"
"github.com/pion/dtls/v2/examples/util"
"github.com/pion/dtls/v2/pkg/crypto/selfsign"
)
+var TPMDEVICES = []string{"/dev/tpm0", "/dev/tpmrm0"}
+
+func OpenTPM(path string) (io.ReadWriteCloser, error) {
+ if slices.Contains(TPMDEVICES, path) {
+ return tpmutil.OpenTPM(path)
+ } else if path == "simulator" {
+ return simulator.GetWithFixedSeedInsecure(1073741825)
+ } else {
+ return net.Dial("tcp", path)
+ }
+}
+
+const (
+ tpmPath = "127.0.0.1:2321"
+)
+
func main() {
// Prepare the IP to connect to
addr := &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: 4444}
+ var err error
+ rwc, err := OpenTPM(tpmPath)
+ if err != nil {
+ log.Fatalf("can't open TPM %q: %v", tpmPath, err)
+ }
+ defer func() {
+ rwc.Close()
+ }()
+
+ k, err := client.LoadCachedKey(rwc, tpmutil.Handle(0x81008000), nil) // ecc
+ //k, err := client.LoadCachedKey(rwc, tpmutil.Handle(0x81008001), nil) // rsapss
+ //k, err := client.LoadCachedKey(rwc, tpmutil.Handle(0x81008002), nil) // rsassa
+ util.Check(err)
+
+ signer, err := k.GetSigner()
+ util.Check(err)
+
+ // privatekey also implements signer
+ // signer, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+ // util.Check(err)
+
// Generate a certificate and private key to secure the connection
- certificate, genErr := selfsign.GenerateSelfSigned()
+ certificate, genErr := selfsign.GenerateSelfSignedSigner(signer)
util.Check(genErr)
// Create parent context to cleanup handshaking connections on exit.
diff --git a/go.mod b/go.mod
index dfaff6f..e4b9eda 100644
--- a/go.mod
+++ b/go.mod
@@ -1,10 +1,27 @@
module github.com/pion/dtls/v2
require (
+ github.com/google/go-tpm v0.9.0
+ github.com/google/go-tpm-tools v0.4.4
github.com/pion/logging v0.2.2
github.com/pion/transport/v3 v3.0.2
+ github.com/salrashid123/signer/tpm v0.0.0-20240520114507-7047274c22ce
golang.org/x/crypto v0.23.0
golang.org/x/net v0.25.0
)
+require (
+ github.com/golang/protobuf v1.5.3 // indirect
+ github.com/google/go-configfs-tsm v0.2.2 // indirect
+ github.com/google/go-sev-guest v0.9.3 // indirect
+ github.com/google/go-tdx-guest v0.3.1 // indirect
+ github.com/google/logger v1.1.1 // indirect
+ github.com/google/uuid v1.3.1 // indirect
+ github.com/pborman/uuid v1.2.1 // indirect
+ github.com/pkg/errors v0.9.1 // indirect
+ go.uber.org/multierr v1.11.0 // indirect
+ golang.org/x/sys v0.20.0 // indirect
+ google.golang.org/protobuf v1.31.0 // indirect
+)
+
go 1.19
diff --git a/go.sum b/go.sum
index b6153ae..87c4454 100644
--- a/go.sum
+++ b/go.sum
@@ -1,10 +1,41 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
+github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/google/certificate-transparency-go v1.1.2 h1:4hE0GEId6NAW28dFpC+LrRGwQX5dtmXQGDbg8+/MZOM=
+github.com/google/go-attestation v0.5.0 h1:jXtAWT2sw2Yu8mYU0BC7FDidR+ngxFPSE+pl6IUu3/0=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
+github.com/google/go-configfs-tsm v0.2.2 h1:YnJ9rXIOj5BYD7/0DNnzs8AOp7UcvjfTvt215EWcs98=
+github.com/google/go-configfs-tsm v0.2.2/go.mod h1:EL1GTDFMb5PZQWDviGfZV9n87WeGTR/JUg13RfwkgRo=
+github.com/google/go-sev-guest v0.9.3 h1:GOJ+EipURdeWFl/YYdgcCxyPeMgQUWlI056iFkBD8UU=
+github.com/google/go-sev-guest v0.9.3/go.mod h1:hc1R4R6f8+NcJwITs0L90fYWTsBpd1Ix+Gur15sqHDs=
+github.com/google/go-tdx-guest v0.3.1 h1:gl0KvjdsD4RrJzyLefDOvFOUH3NAJri/3qvaL5m83Iw=
+github.com/google/go-tdx-guest v0.3.1/go.mod h1:/rc3d7rnPykOPuY8U9saMyEps0PZDThLk/RygXm04nE=
+github.com/google/go-tpm v0.9.0 h1:sQF6YqWMi+SCXpsmS3fd21oPy/vSddwZry4JnmltHVk=
+github.com/google/go-tpm v0.9.0/go.mod h1:FkNVkc6C+IsvDI9Jw1OveJmxGZUUaKxtrpOS47QWKfU=
+github.com/google/go-tpm-tools v0.4.4 h1:oiQfAIkc6xTy9Fl5NKTeTJkBTlXdHsxAofmQyxBKY98=
+github.com/google/go-tpm-tools v0.4.4/go.mod h1:T8jXkp2s+eltnCDIsXR84/MTcVU9Ja7bh3Mit0pa4AY=
+github.com/google/go-tspi v0.3.0 h1:ADtq8RKfP+jrTyIWIZDIYcKOMecRqNJFOew2IT0Inus=
+github.com/google/logger v1.1.1 h1:+6Z2geNxc9G+4D4oDO9njjjn2d0wN5d7uOo0vOIW1NQ=
+github.com/google/logger v1.1.1/go.mod h1:BkeJZ+1FhQ+/d087r4dzojEg1u2ZX+ZqG1jTUrLM+zQ=
+github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
+github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/pborman/uuid v1.2.1 h1:+ZZIw58t/ozdjRaXh/3awHfmWRbzYxJoAdNJxe/3pvw=
+github.com/pborman/uuid v1.2.1/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY=
github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms=
github.com/pion/transport/v3 v3.0.2 h1:r+40RJR25S9w3jbA6/5uEPTzcdn7ncyU44RWCbHkLg4=
github.com/pion/transport/v3 v3.0.2/go.mod h1:nIToODoOlb5If2jF9y2Igfx3PFYWfuXi37m0IlWa/D0=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/salrashid123/signer/tpm v0.0.0-20240520114507-7047274c22ce h1:68WgsglS7fRWMvXuEBXCvd8KJ4fZCtJlwxdmvYZA4WQ=
+github.com/salrashid123/signer/tpm v0.0.0-20240520114507-7047274c22ce/go.mod h1:D1+aHT/KM+rEbyPaAyc2j7k177ZRx26bShZqzXlALFU=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
@@ -12,8 +43,11 @@ github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
+go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
+go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
@@ -36,6 +70,7 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -43,6 +78,8 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
+golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
@@ -60,6 +97,12 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
+google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/pkg/crypto/selfsign/selfsign.go b/pkg/crypto/selfsign/selfsign.go
index 6ef0167..4227019 100644
--- a/pkg/crypto/selfsign/selfsign.go
+++ b/pkg/crypto/selfsign/selfsign.go
@@ -46,6 +46,86 @@ func SelfSign(key crypto.PrivateKey) (tls.Certificate, error) {
return WithDNS(key, "self-signed cert")
}
+func GenerateSelfSignedSigner(priv crypto.Signer) (tls.Certificate, error) {
+ return SelfWithSigner(priv)
+}
+
+func SelfWithSigner(key crypto.Signer) (tls.Certificate, error) {
+ return WithDNSSigner(key, "self-signed cert")
+}
+
+// WithDNS creates a self-signed certificate from a elliptic curve key
+func WithDNSSigner(key crypto.Signer, cn string, sans ...string) (tls.Certificate, error) {
+ var (
+ pubKey crypto.PublicKey
+ maxBigInt = new(big.Int) // Max random value, a 130-bits integer, i.e 2^130 - 1
+ )
+
+ k := key.Public()
+ switch k.(type) {
+ case ed25519.PublicKey:
+ pubKey = k
+ case *ecdsa.PublicKey:
+ pubKey = k
+ case *rsa.PublicKey:
+ pubKey = k
+ default:
+ return tls.Certificate{}, errInvalidPrivateKey
+ }
+
+ /* #nosec */
+ maxBigInt.Exp(big.NewInt(2), big.NewInt(130), nil).Sub(maxBigInt, big.NewInt(1))
+ /* #nosec */
+ serialNumber, err := rand.Int(rand.Reader, maxBigInt)
+ if err != nil {
+ return tls.Certificate{}, err
+ }
+
+ names := []string{cn}
+ names = append(names, sans...)
+
+ keyUsage := x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign
+ if _, isRSA := key.(*rsa.PrivateKey); isRSA {
+ keyUsage |= x509.KeyUsageKeyEncipherment
+ }
+
+ template := x509.Certificate{
+ ExtKeyUsage: []x509.ExtKeyUsage{
+ x509.ExtKeyUsageClientAuth,
+ x509.ExtKeyUsageServerAuth,
+ },
+ BasicConstraintsValid: true,
+ NotBefore: time.Now(),
+ KeyUsage: keyUsage,
+ NotAfter: time.Now().AddDate(0, 1, 0),
+ SerialNumber: serialNumber,
+ Version: 2,
+ IsCA: true,
+ DNSNames: names,
+ Subject: pkix.Name{
+ CommonName: cn,
+ },
+ // w/ rsapss
+ //SignatureAlgorithm: x509.SHA256WithRSAPSS,
+ }
+
+ raw, err := x509.CreateCertificate(rand.Reader, &template, &template, pubKey, key)
+ if err != nil {
+ return tls.Certificate{}, err
+ }
+
+ leaf, err := x509.ParseCertificate(raw)
+ if err != nil {
+ return tls.Certificate{}, err
+ }
+
+ return tls.Certificate{
+ Certificate: [][]byte{raw},
+ PrivateKey: key,
+ Leaf: leaf,
+ }, nil
+}
+
// WithDNS creates a self-signed certificate from a elliptic curve key
func WithDNS(key crypto.PrivateKey, cn string, sans ...string) (tls.Certificate, error) {
var (
diff --git a/pkg/crypto/signaturehash/signaturehash.go b/pkg/crypto/signaturehash/signaturehash.go
index 2561acc..68e6bcb 100644
--- a/pkg/crypto/signaturehash/signaturehash.go
+++ b/pkg/crypto/signaturehash/signaturehash.go
@@ -57,6 +57,18 @@ func (a *Algorithm) isCompatible(privateKey crypto.PrivateKey) bool {
return a.Signature == signature.ECDSA
case *rsa.PrivateKey:
return a.Signature == signature.RSA
+ case crypto.Signer:
+ s := privateKey.(crypto.Signer).Public()
+ switch s.(type) {
+ case ed25519.PublicKey:
+ return a.Signature == signature.Ed25519
+ case *ecdsa.PublicKey:
+ return a.Signature == signature.ECDSA
+ case *rsa.PublicKey:
+ return a.Signature == signature.RSA
+ default:
+ return false
+ }
default:
return false
}
|
For certificate-based authentication, it is possible that the private key resides in hardware such as Trusted Platform Module (TPM) and the only way in Golang to access it via the crypto.Signer interface. Any code paths that deal with a private key should use the crypto.Signer interface which comes with a function called Public() and it can be used to determine the type of key used. Fixes pion#524
Summary
Allow users to supply a crypto.Signer implementation instead of an actual private key to dtls.v2.Config.
This would allow an abstration allowing customers to use keys embedded into hardware (TPM) or KMS systems that implement that interface.
Motivation
Right now users have to supply the raw private key to Config but with TPM, KMS or PKCS-11 systems, the key is not extractactable but is 'available' for use sometimes through a a
crypto.signer
interface:eg for TPM
with this feature, a client on a device can use its embedded key for dtls connections
Additional context
some additional refernces (untested at scale)
JWT:
mTLS
The text was updated successfully, but these errors were encountered: