sign.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. package cert
  2. import (
  3. "crypto/ecdsa"
  4. "crypto/ed25519"
  5. "crypto/elliptic"
  6. "crypto/rand"
  7. "crypto/sha256"
  8. "fmt"
  9. "net/netip"
  10. "time"
  11. "github.com/slackhq/nebula/cert/p256"
  12. )
  13. // TBSCertificate represents a certificate intended to be signed.
  14. // It is invalid to use this structure as a Certificate.
  15. type TBSCertificate struct {
  16. Version Version
  17. Name string
  18. Networks []netip.Prefix
  19. UnsafeNetworks []netip.Prefix
  20. Groups []string
  21. IsCA bool
  22. NotBefore time.Time
  23. NotAfter time.Time
  24. PublicKey []byte
  25. Curve Curve
  26. issuer string
  27. }
  28. type beingSignedCertificate interface {
  29. // fromTBSCertificate copies the values from the TBSCertificate to this versions internal representation
  30. // Implementations must validate the resulting certificate contains valid information
  31. fromTBSCertificate(*TBSCertificate) error
  32. // marshalForSigning returns the bytes that should be signed
  33. marshalForSigning() ([]byte, error)
  34. // setSignature sets the signature for the certificate that has just been signed. The signature must not be blank.
  35. setSignature([]byte) error
  36. }
  37. type SignerLambda func(certBytes []byte) ([]byte, error)
  38. // Sign will create a sealed certificate using details provided by the TBSCertificate as long as those
  39. // details do not violate constraints of the signing certificate.
  40. // If the TBSCertificate is a CA then signer must be nil.
  41. func (t *TBSCertificate) Sign(signer Certificate, curve Curve, key []byte) (Certificate, error) {
  42. switch t.Curve {
  43. case Curve_CURVE25519:
  44. pk := ed25519.PrivateKey(key)
  45. sp := func(certBytes []byte) ([]byte, error) {
  46. sig := ed25519.Sign(pk, certBytes)
  47. return sig, nil
  48. }
  49. return t.SignWith(signer, curve, sp)
  50. case Curve_P256:
  51. pk, err := ecdsa.ParseRawPrivateKey(elliptic.P256(), key)
  52. if err != nil {
  53. return nil, err
  54. }
  55. sp := func(certBytes []byte) ([]byte, error) {
  56. // We need to hash first for ECDSA
  57. // - https://pkg.go.dev/crypto/ecdsa#SignASN1
  58. hashed := sha256.Sum256(certBytes)
  59. return ecdsa.SignASN1(rand.Reader, pk, hashed[:])
  60. }
  61. return t.SignWith(signer, curve, sp)
  62. default:
  63. return nil, fmt.Errorf("invalid curve: %s", t.Curve)
  64. }
  65. }
  66. // SignWith does the same thing as sign, but uses the function in `sp` to calculate the signature.
  67. // You should only use SignWith if you do not have direct access to your private key.
  68. func (t *TBSCertificate) SignWith(signer Certificate, curve Curve, sp SignerLambda) (Certificate, error) {
  69. if curve != t.Curve {
  70. return nil, fmt.Errorf("curve in cert and private key supplied don't match")
  71. }
  72. if signer != nil {
  73. if t.IsCA {
  74. return nil, fmt.Errorf("can not sign a CA certificate with another")
  75. }
  76. err := checkCAConstraints(signer, t.NotBefore, t.NotAfter, t.Groups, t.Networks, t.UnsafeNetworks)
  77. if err != nil {
  78. return nil, err
  79. }
  80. issuer, err := signer.Fingerprint()
  81. if err != nil {
  82. return nil, fmt.Errorf("error computing issuer: %v", err)
  83. }
  84. t.issuer = issuer
  85. } else {
  86. if !t.IsCA {
  87. return nil, fmt.Errorf("self signed certificates must have IsCA set to true")
  88. }
  89. }
  90. var c beingSignedCertificate
  91. switch t.Version {
  92. case Version1:
  93. c = &certificateV1{}
  94. err := c.fromTBSCertificate(t)
  95. if err != nil {
  96. return nil, err
  97. }
  98. case Version2:
  99. c = &certificateV2{}
  100. err := c.fromTBSCertificate(t)
  101. if err != nil {
  102. return nil, err
  103. }
  104. default:
  105. return nil, fmt.Errorf("unknown cert version %d", t.Version)
  106. }
  107. certBytes, err := c.marshalForSigning()
  108. if err != nil {
  109. return nil, err
  110. }
  111. sig, err := sp(certBytes)
  112. if err != nil {
  113. return nil, err
  114. }
  115. if curve == Curve_P256 {
  116. sig, err = p256.Normalize(sig)
  117. if err != nil {
  118. return nil, err
  119. }
  120. }
  121. err = c.setSignature(sig)
  122. if err != nil {
  123. return nil, err
  124. }
  125. sc, ok := c.(Certificate)
  126. if !ok {
  127. return nil, fmt.Errorf("invalid certificate")
  128. }
  129. return sc, nil
  130. }
  131. func comparePrefix(a, b netip.Prefix) int {
  132. addr := a.Addr().Compare(b.Addr())
  133. if addr == 0 {
  134. return a.Bits() - b.Bits()
  135. }
  136. return addr
  137. }
  138. // findDuplicatePrefix returns an error if there is a duplicate prefix in the pre-sorted input slice sortedPrefixes
  139. func findDuplicatePrefix(sortedPrefixes []netip.Prefix) error {
  140. if len(sortedPrefixes) < 2 {
  141. return nil
  142. }
  143. for i := 1; i < len(sortedPrefixes); i++ {
  144. if comparePrefix(sortedPrefixes[i], sortedPrefixes[i-1]) == 0 {
  145. return NewErrInvalidCertificateProperties("duplicate network detected: %v", sortedPrefixes[i])
  146. }
  147. }
  148. return nil
  149. }