blob: b4649f117f5cf4bdcccb3a87321b39898d3603fa [file] [log] [blame]
giolekva6bb21c22021-12-29 21:31:08 +04001package main
2
3import (
4 "crypto/ed25519"
5 "crypto/rand"
6 "errors"
7 "io"
8 "net"
9 "time"
10
11 "github.com/slackhq/nebula/cert"
12 "golang.org/x/crypto/curve25519"
13)
14
15type CertificateAuthority struct {
16 PrivateKey []byte `json:"private_key"`
17 Certificate []byte `json:"certificate"`
18}
19
20func CreateCertificateAuthority(name string) (*CertificateAuthority, error) {
21 t := time.Now().Add(time.Duration(-1 * time.Second))
22 rawPub, rawPriv, err := ed25519.GenerateKey(rand.Reader)
23 if err != nil {
24 return nil, err
25 }
26 nc := cert.NebulaCertificate{
27 Details: cert.NebulaCertificateDetails{
28 Name: name,
29 NotBefore: t,
30 NotAfter: t.Add(time.Duration(8760 * time.Hour)),
31 PublicKey: rawPub,
32 IsCA: true,
33 },
34 }
35 if err := nc.Sign(rawPriv); err != nil {
36 return nil, err
37 }
38 certSerialized, err := nc.MarshalToPEM()
39 if err != nil {
40 return nil, err
41 }
42 privKeySerialzied := cert.MarshalEd25519PrivateKey(rawPriv)
43 return &CertificateAuthority{
44 privKeySerialzied,
45 certSerialized,
46 }, nil
47}
48
49type NebulaNode struct {
50 PrivateKey []byte `json:"private_key,omitempty"`
51 Certificate []byte `json:"certificate"`
52}
53
54func SignNebulaNode(rawCAPrivateKey []byte, rawCACert []byte, nodeName string, nodePublicKey []byte, ip *net.IPNet) (*NebulaNode, error) {
55 caKey, _, err := cert.UnmarshalEd25519PrivateKey(rawCAPrivateKey)
56 if err != nil {
57 return nil, err
58 }
59 caCert, _, err := cert.UnmarshalNebulaCertificateFromPEM(rawCACert)
60 if err != nil {
61 return nil, err
62 }
63
64 if err := caCert.VerifyPrivateKey(caKey); err != nil {
65 return nil, err
66 }
67 issuer, err := caCert.Sha256Sum()
68 if err != nil {
69 return nil, err
70 }
71 if caCert.Expired(time.Now()) {
72 return nil, errors.New("ca certificate is expired")
73 }
74 var pub, priv []byte
75 if nodePublicKey != nil {
76 var err error
77 pub, _, err = cert.UnmarshalX25519PublicKey(nodePublicKey)
78 if err != nil {
79 return nil, err
80 }
81 } else {
82 var rawPriv []byte
83 var err error
84 pub, rawPriv, err = x25519Keypair()
85 if err != nil {
86 return nil, err
87 }
88 priv = cert.MarshalX25519PrivateKey(rawPriv)
89 }
90 t := time.Now().Add(time.Duration(-1 * time.Second))
91 nc := cert.NebulaCertificate{
92 Details: cert.NebulaCertificateDetails{
93 Name: nodeName,
94 Ips: []*net.IPNet{ip},
95 NotBefore: t,
96 NotAfter: caCert.Details.NotAfter.Add(time.Duration(-1 * time.Second)),
97 PublicKey: pub,
98 IsCA: false,
99 Issuer: issuer,
100 },
101 }
102 if err := nc.CheckRootConstrains(caCert); err != nil {
103 return nil, err
104 }
105 if err := nc.Sign(caKey); err != nil {
106 return nil, err
107 }
108 certSerialized, err := nc.MarshalToPEM()
109 if err != nil {
110 return nil, err
111 }
112 return &NebulaNode{
113 PrivateKey: priv,
114 Certificate: certSerialized,
115 }, nil
116}
117
118func x25519Keypair() ([]byte, []byte, error) {
119 var pubkey, privkey [32]byte
120 if _, err := io.ReadFull(rand.Reader, privkey[:]); err != nil {
121 return nil, nil, err
122 }
123 curve25519.ScalarBaseMult(&pubkey, &privkey)
124 return pubkey[:], privkey[:], nil
125}