nebula/noiseutil/pkcs11.go

51 lines
1.2 KiB
Go

package noiseutil
import (
"crypto/ecdh"
"fmt"
"strings"
"github.com/slackhq/nebula/pkclient"
"github.com/flynn/noise"
)
// DHP256PKCS11 is the NIST P-256 ECDH function
var DHP256PKCS11 noise.DHFunc = newNISTP11Curve("P256", ecdh.P256(), 32)
type nistP11Curve struct {
nistCurve
}
func newNISTP11Curve(name string, curve ecdh.Curve, byteLen int) nistP11Curve {
return nistP11Curve{
newNISTCurve(name, curve, byteLen),
}
}
func (c nistP11Curve) DH(privkey, pubkey []byte) ([]byte, error) {
//for this function "privkey" is actually a pkcs11 URI
pkStr := string(privkey)
//to set up a handshake, we need to also do non-pkcs11-DH. Handle that here.
if !strings.HasPrefix(pkStr, "pkcs11:") {
return DHP256.DH(privkey, pubkey)
}
ecdhPubKey, err := c.curve.NewPublicKey(pubkey)
if err != nil {
return nil, fmt.Errorf("unable to unmarshal pubkey: %w", err)
}
//this is not the most performant way to do this (a long-lived client would be better)
//but, it works, and helps avoid problems with stale sessions and HSMs used by multiple users.
client, err := pkclient.FromUrl(pkStr)
if err != nil {
return nil, err
}
defer func(client *pkclient.PKClient) {
_ = client.Close()
}(client)
return client.DeriveNoise(ecdhPubKey.Bytes())
}