| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 | package certimport (	"crypto/ecdsa"	"crypto/ed25519"	"crypto/elliptic"	"crypto/rand"	"crypto/sha256"	"fmt"	"math/big"	"net/netip"	"time")// TBSCertificate represents a certificate intended to be signed.// It is invalid to use this structure as a Certificate.type TBSCertificate struct {	Version        Version	Name           string	Networks       []netip.Prefix	UnsafeNetworks []netip.Prefix	Groups         []string	IsCA           bool	NotBefore      time.Time	NotAfter       time.Time	PublicKey      []byte	Curve          Curve	issuer         string}type beingSignedCertificate interface {	// fromTBSCertificate copies the values from the TBSCertificate to this versions internal representation	// Implementations must validate the resulting certificate contains valid information	fromTBSCertificate(*TBSCertificate) error	// marshalForSigning returns the bytes that should be signed	marshalForSigning() ([]byte, error)	// setSignature sets the signature for the certificate that has just been signed. The signature must not be blank.	setSignature([]byte) error}type SignerLambda func(certBytes []byte) ([]byte, error)// Sign will create a sealed certificate using details provided by the TBSCertificate as long as those// details do not violate constraints of the signing certificate.// If the TBSCertificate is a CA then signer must be nil.func (t *TBSCertificate) Sign(signer Certificate, curve Curve, key []byte) (Certificate, error) {	switch t.Curve {	case Curve_CURVE25519:		pk := ed25519.PrivateKey(key)		sp := func(certBytes []byte) ([]byte, error) {			sig := ed25519.Sign(pk, certBytes)			return sig, nil		}		return t.SignWith(signer, curve, sp)	case Curve_P256:		pk := &ecdsa.PrivateKey{			PublicKey: ecdsa.PublicKey{				Curve: elliptic.P256(),			},			// ref: https://github.com/golang/go/blob/go1.19/src/crypto/x509/sec1.go#L95			D: new(big.Int).SetBytes(key),		}		// ref: https://github.com/golang/go/blob/go1.19/src/crypto/x509/sec1.go#L119		pk.X, pk.Y = pk.Curve.ScalarBaseMult(key)		sp := func(certBytes []byte) ([]byte, error) {			// We need to hash first for ECDSA			// - https://pkg.go.dev/crypto/ecdsa#SignASN1			hashed := sha256.Sum256(certBytes)			return ecdsa.SignASN1(rand.Reader, pk, hashed[:])		}		return t.SignWith(signer, curve, sp)	default:		return nil, fmt.Errorf("invalid curve: %s", t.Curve)	}}// SignWith does the same thing as sign, but uses the function in `sp` to calculate the signature.// You should only use SignWith if you do not have direct access to your private key.func (t *TBSCertificate) SignWith(signer Certificate, curve Curve, sp SignerLambda) (Certificate, error) {	if curve != t.Curve {		return nil, fmt.Errorf("curve in cert and private key supplied don't match")	}	if signer != nil {		if t.IsCA {			return nil, fmt.Errorf("can not sign a CA certificate with another")		}		err := checkCAConstraints(signer, t.NotBefore, t.NotAfter, t.Groups, t.Networks, t.UnsafeNetworks)		if err != nil {			return nil, err		}		issuer, err := signer.Fingerprint()		if err != nil {			return nil, fmt.Errorf("error computing issuer: %v", err)		}		t.issuer = issuer	} else {		if !t.IsCA {			return nil, fmt.Errorf("self signed certificates must have IsCA set to true")		}	}	var c beingSignedCertificate	switch t.Version {	case Version1:		c = &certificateV1{}		err := c.fromTBSCertificate(t)		if err != nil {			return nil, err		}	case Version2:		c = &certificateV2{}		err := c.fromTBSCertificate(t)		if err != nil {			return nil, err		}	default:		return nil, fmt.Errorf("unknown cert version %d", t.Version)	}	certBytes, err := c.marshalForSigning()	if err != nil {		return nil, err	}	sig, err := sp(certBytes)	if err != nil {		return nil, err	}	err = c.setSignature(sig)	if err != nil {		return nil, err	}	sc, ok := c.(Certificate)	if !ok {		return nil, fmt.Errorf("invalid certificate")	}	return sc, nil}func comparePrefix(a, b netip.Prefix) int {	addr := a.Addr().Compare(b.Addr())	if addr == 0 {		return a.Bits() - b.Bits()	}	return addr}// findDuplicatePrefix returns an error if there is a duplicate prefix in the pre-sorted input slice sortedPrefixesfunc findDuplicatePrefix(sortedPrefixes []netip.Prefix) error {	if len(sortedPrefixes) < 2 {		return nil	}	for i := 1; i < len(sortedPrefixes); i++ {		if comparePrefix(sortedPrefixes[i], sortedPrefixes[i-1]) == 0 {			return NewErrInvalidCertificateProperties("duplicate network detected: %v", sortedPrefixes[i])		}	}	return nil}
 |