pkcs11.go 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. package noiseutil
  2. import (
  3. "crypto/ecdh"
  4. "fmt"
  5. "strings"
  6. "github.com/slackhq/nebula/pkclient"
  7. "github.com/flynn/noise"
  8. )
  9. // DHP256PKCS11 is the NIST P-256 ECDH function
  10. var DHP256PKCS11 noise.DHFunc = newNISTP11Curve("P256", ecdh.P256(), 32)
  11. type nistP11Curve struct {
  12. nistCurve
  13. }
  14. func newNISTP11Curve(name string, curve ecdh.Curve, byteLen int) nistP11Curve {
  15. return nistP11Curve{
  16. newNISTCurve(name, curve, byteLen),
  17. }
  18. }
  19. func (c nistP11Curve) DH(privkey, pubkey []byte) ([]byte, error) {
  20. //for this function "privkey" is actually a pkcs11 URI
  21. pkStr := string(privkey)
  22. //to set up a handshake, we need to also do non-pkcs11-DH. Handle that here.
  23. if !strings.HasPrefix(pkStr, "pkcs11:") {
  24. return DHP256.DH(privkey, pubkey)
  25. }
  26. ecdhPubKey, err := c.curve.NewPublicKey(pubkey)
  27. if err != nil {
  28. return nil, fmt.Errorf("unable to unmarshal pubkey: %w", err)
  29. }
  30. //this is not the most performant way to do this (a long-lived client would be better)
  31. //but, it works, and helps avoid problems with stale sessions and HSMs used by multiple users.
  32. client, err := pkclient.FromUrl(pkStr)
  33. if err != nil {
  34. return nil, err
  35. }
  36. defer func(client *pkclient.PKClient) {
  37. _ = client.Close()
  38. }(client)
  39. return client.DeriveNoise(ecdhPubKey.Bytes())
  40. }