2
0

cert.go 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029
  1. package cert
  2. import (
  3. "bytes"
  4. "crypto/ecdh"
  5. "crypto/ecdsa"
  6. "crypto/ed25519"
  7. "crypto/elliptic"
  8. "crypto/rand"
  9. "crypto/sha256"
  10. "encoding/binary"
  11. "encoding/hex"
  12. "encoding/json"
  13. "encoding/pem"
  14. "errors"
  15. "fmt"
  16. "math"
  17. "math/big"
  18. "net"
  19. "sync/atomic"
  20. "time"
  21. "golang.org/x/crypto/curve25519"
  22. "google.golang.org/protobuf/proto"
  23. )
  24. const publicKeyLen = 32
  25. const (
  26. CertBanner = "NEBULA CERTIFICATE"
  27. X25519PrivateKeyBanner = "NEBULA X25519 PRIVATE KEY"
  28. X25519PublicKeyBanner = "NEBULA X25519 PUBLIC KEY"
  29. EncryptedEd25519PrivateKeyBanner = "NEBULA ED25519 ENCRYPTED PRIVATE KEY"
  30. Ed25519PrivateKeyBanner = "NEBULA ED25519 PRIVATE KEY"
  31. Ed25519PublicKeyBanner = "NEBULA ED25519 PUBLIC KEY"
  32. P256PrivateKeyBanner = "NEBULA P256 PRIVATE KEY"
  33. P256PublicKeyBanner = "NEBULA P256 PUBLIC KEY"
  34. EncryptedECDSAP256PrivateKeyBanner = "NEBULA ECDSA P256 ENCRYPTED PRIVATE KEY"
  35. ECDSAP256PrivateKeyBanner = "NEBULA ECDSA P256 PRIVATE KEY"
  36. )
  37. type NebulaCertificate struct {
  38. Details NebulaCertificateDetails
  39. Signature []byte
  40. // the cached hex string of the calculated sha256sum
  41. // for VerifyWithCache
  42. sha256sum atomic.Pointer[string]
  43. // the cached public key bytes if they were verified as the signer
  44. // for VerifyWithCache
  45. signatureVerified atomic.Pointer[[]byte]
  46. }
  47. type NebulaCertificateDetails struct {
  48. Name string
  49. Ips []*net.IPNet
  50. Subnets []*net.IPNet
  51. Groups []string
  52. NotBefore time.Time
  53. NotAfter time.Time
  54. PublicKey []byte
  55. IsCA bool
  56. Issuer string
  57. // Map of groups for faster lookup
  58. InvertedGroups map[string]struct{}
  59. Curve Curve
  60. }
  61. type NebulaEncryptedData struct {
  62. EncryptionMetadata NebulaEncryptionMetadata
  63. Ciphertext []byte
  64. }
  65. type NebulaEncryptionMetadata struct {
  66. EncryptionAlgorithm string
  67. Argon2Parameters Argon2Parameters
  68. }
  69. type m map[string]interface{}
  70. // Returned if we try to unmarshal an encrypted private key without a passphrase
  71. var ErrPrivateKeyEncrypted = errors.New("private key must be decrypted")
  72. // UnmarshalNebulaCertificate will unmarshal a protobuf byte representation of a nebula cert
  73. func UnmarshalNebulaCertificate(b []byte) (*NebulaCertificate, error) {
  74. if len(b) == 0 {
  75. return nil, fmt.Errorf("nil byte array")
  76. }
  77. var rc RawNebulaCertificate
  78. err := proto.Unmarshal(b, &rc)
  79. if err != nil {
  80. return nil, err
  81. }
  82. if rc.Details == nil {
  83. return nil, fmt.Errorf("encoded Details was nil")
  84. }
  85. if len(rc.Details.Ips)%2 != 0 {
  86. return nil, fmt.Errorf("encoded IPs should be in pairs, an odd number was found")
  87. }
  88. if len(rc.Details.Subnets)%2 != 0 {
  89. return nil, fmt.Errorf("encoded Subnets should be in pairs, an odd number was found")
  90. }
  91. nc := NebulaCertificate{
  92. Details: NebulaCertificateDetails{
  93. Name: rc.Details.Name,
  94. Groups: make([]string, len(rc.Details.Groups)),
  95. Ips: make([]*net.IPNet, len(rc.Details.Ips)/2),
  96. Subnets: make([]*net.IPNet, len(rc.Details.Subnets)/2),
  97. NotBefore: time.Unix(rc.Details.NotBefore, 0),
  98. NotAfter: time.Unix(rc.Details.NotAfter, 0),
  99. PublicKey: make([]byte, len(rc.Details.PublicKey)),
  100. IsCA: rc.Details.IsCA,
  101. InvertedGroups: make(map[string]struct{}),
  102. Curve: rc.Details.Curve,
  103. },
  104. Signature: make([]byte, len(rc.Signature)),
  105. }
  106. copy(nc.Signature, rc.Signature)
  107. copy(nc.Details.Groups, rc.Details.Groups)
  108. nc.Details.Issuer = hex.EncodeToString(rc.Details.Issuer)
  109. if len(rc.Details.PublicKey) < publicKeyLen {
  110. return nil, fmt.Errorf("Public key was fewer than 32 bytes; %v", len(rc.Details.PublicKey))
  111. }
  112. copy(nc.Details.PublicKey, rc.Details.PublicKey)
  113. for i, rawIp := range rc.Details.Ips {
  114. if i%2 == 0 {
  115. nc.Details.Ips[i/2] = &net.IPNet{IP: int2ip(rawIp)}
  116. } else {
  117. nc.Details.Ips[i/2].Mask = net.IPMask(int2ip(rawIp))
  118. }
  119. }
  120. for i, rawIp := range rc.Details.Subnets {
  121. if i%2 == 0 {
  122. nc.Details.Subnets[i/2] = &net.IPNet{IP: int2ip(rawIp)}
  123. } else {
  124. nc.Details.Subnets[i/2].Mask = net.IPMask(int2ip(rawIp))
  125. }
  126. }
  127. for _, g := range rc.Details.Groups {
  128. nc.Details.InvertedGroups[g] = struct{}{}
  129. }
  130. return &nc, nil
  131. }
  132. // UnmarshalNebulaCertificateFromPEM will unmarshal the first pem block in a byte array, returning any non consumed data
  133. // or an error on failure
  134. func UnmarshalNebulaCertificateFromPEM(b []byte) (*NebulaCertificate, []byte, error) {
  135. p, r := pem.Decode(b)
  136. if p == nil {
  137. return nil, r, fmt.Errorf("input did not contain a valid PEM encoded block")
  138. }
  139. if p.Type != CertBanner {
  140. return nil, r, fmt.Errorf("bytes did not contain a proper nebula certificate banner")
  141. }
  142. nc, err := UnmarshalNebulaCertificate(p.Bytes)
  143. return nc, r, err
  144. }
  145. func MarshalPrivateKey(curve Curve, b []byte) []byte {
  146. switch curve {
  147. case Curve_CURVE25519:
  148. return pem.EncodeToMemory(&pem.Block{Type: X25519PrivateKeyBanner, Bytes: b})
  149. case Curve_P256:
  150. return pem.EncodeToMemory(&pem.Block{Type: P256PrivateKeyBanner, Bytes: b})
  151. default:
  152. return nil
  153. }
  154. }
  155. func MarshalSigningPrivateKey(curve Curve, b []byte) []byte {
  156. switch curve {
  157. case Curve_CURVE25519:
  158. return pem.EncodeToMemory(&pem.Block{Type: Ed25519PrivateKeyBanner, Bytes: b})
  159. case Curve_P256:
  160. return pem.EncodeToMemory(&pem.Block{Type: ECDSAP256PrivateKeyBanner, Bytes: b})
  161. default:
  162. return nil
  163. }
  164. }
  165. // MarshalX25519PrivateKey is a simple helper to PEM encode an X25519 private key
  166. func MarshalX25519PrivateKey(b []byte) []byte {
  167. return pem.EncodeToMemory(&pem.Block{Type: X25519PrivateKeyBanner, Bytes: b})
  168. }
  169. // MarshalEd25519PrivateKey is a simple helper to PEM encode an Ed25519 private key
  170. func MarshalEd25519PrivateKey(key ed25519.PrivateKey) []byte {
  171. return pem.EncodeToMemory(&pem.Block{Type: Ed25519PrivateKeyBanner, Bytes: key})
  172. }
  173. func UnmarshalPrivateKey(b []byte) ([]byte, []byte, Curve, error) {
  174. k, r := pem.Decode(b)
  175. if k == nil {
  176. return nil, r, 0, fmt.Errorf("input did not contain a valid PEM encoded block")
  177. }
  178. var expectedLen int
  179. var curve Curve
  180. switch k.Type {
  181. case X25519PrivateKeyBanner:
  182. expectedLen = 32
  183. curve = Curve_CURVE25519
  184. case P256PrivateKeyBanner:
  185. expectedLen = 32
  186. curve = Curve_P256
  187. default:
  188. return nil, r, 0, fmt.Errorf("bytes did not contain a proper nebula private key banner")
  189. }
  190. if len(k.Bytes) != expectedLen {
  191. return nil, r, 0, fmt.Errorf("key was not %d bytes, is invalid %s private key", expectedLen, curve)
  192. }
  193. return k.Bytes, r, curve, nil
  194. }
  195. func UnmarshalSigningPrivateKey(b []byte) ([]byte, []byte, Curve, error) {
  196. k, r := pem.Decode(b)
  197. if k == nil {
  198. return nil, r, 0, fmt.Errorf("input did not contain a valid PEM encoded block")
  199. }
  200. var curve Curve
  201. switch k.Type {
  202. case EncryptedEd25519PrivateKeyBanner:
  203. return nil, nil, Curve_CURVE25519, ErrPrivateKeyEncrypted
  204. case EncryptedECDSAP256PrivateKeyBanner:
  205. return nil, nil, Curve_P256, ErrPrivateKeyEncrypted
  206. case Ed25519PrivateKeyBanner:
  207. curve = Curve_CURVE25519
  208. if len(k.Bytes) != ed25519.PrivateKeySize {
  209. return nil, r, 0, fmt.Errorf("key was not %d bytes, is invalid Ed25519 private key", ed25519.PrivateKeySize)
  210. }
  211. case ECDSAP256PrivateKeyBanner:
  212. curve = Curve_P256
  213. if len(k.Bytes) != 32 {
  214. return nil, r, 0, fmt.Errorf("key was not 32 bytes, is invalid ECDSA P256 private key")
  215. }
  216. default:
  217. return nil, r, 0, fmt.Errorf("bytes did not contain a proper nebula Ed25519/ECDSA private key banner")
  218. }
  219. return k.Bytes, r, curve, nil
  220. }
  221. // EncryptAndMarshalSigningPrivateKey is a simple helper to encrypt and PEM encode a private key
  222. func EncryptAndMarshalSigningPrivateKey(curve Curve, b []byte, passphrase []byte, kdfParams *Argon2Parameters) ([]byte, error) {
  223. ciphertext, err := aes256Encrypt(passphrase, kdfParams, b)
  224. if err != nil {
  225. return nil, err
  226. }
  227. b, err = proto.Marshal(&RawNebulaEncryptedData{
  228. EncryptionMetadata: &RawNebulaEncryptionMetadata{
  229. EncryptionAlgorithm: "AES-256-GCM",
  230. Argon2Parameters: &RawNebulaArgon2Parameters{
  231. Version: kdfParams.version,
  232. Memory: kdfParams.Memory,
  233. Parallelism: uint32(kdfParams.Parallelism),
  234. Iterations: kdfParams.Iterations,
  235. Salt: kdfParams.salt,
  236. },
  237. },
  238. Ciphertext: ciphertext,
  239. })
  240. if err != nil {
  241. return nil, err
  242. }
  243. switch curve {
  244. case Curve_CURVE25519:
  245. return pem.EncodeToMemory(&pem.Block{Type: EncryptedEd25519PrivateKeyBanner, Bytes: b}), nil
  246. case Curve_P256:
  247. return pem.EncodeToMemory(&pem.Block{Type: EncryptedECDSAP256PrivateKeyBanner, Bytes: b}), nil
  248. default:
  249. return nil, fmt.Errorf("invalid curve: %v", curve)
  250. }
  251. }
  252. // UnmarshalX25519PrivateKey will try to pem decode an X25519 private key, returning any other bytes b
  253. // or an error on failure
  254. func UnmarshalX25519PrivateKey(b []byte) ([]byte, []byte, error) {
  255. k, r := pem.Decode(b)
  256. if k == nil {
  257. return nil, r, fmt.Errorf("input did not contain a valid PEM encoded block")
  258. }
  259. if k.Type != X25519PrivateKeyBanner {
  260. return nil, r, fmt.Errorf("bytes did not contain a proper nebula X25519 private key banner")
  261. }
  262. if len(k.Bytes) != publicKeyLen {
  263. return nil, r, fmt.Errorf("key was not 32 bytes, is invalid X25519 private key")
  264. }
  265. return k.Bytes, r, nil
  266. }
  267. // UnmarshalEd25519PrivateKey will try to pem decode an Ed25519 private key, returning any other bytes b
  268. // or an error on failure
  269. func UnmarshalEd25519PrivateKey(b []byte) (ed25519.PrivateKey, []byte, error) {
  270. k, r := pem.Decode(b)
  271. if k == nil {
  272. return nil, r, fmt.Errorf("input did not contain a valid PEM encoded block")
  273. }
  274. if k.Type == EncryptedEd25519PrivateKeyBanner {
  275. return nil, r, ErrPrivateKeyEncrypted
  276. } else if k.Type != Ed25519PrivateKeyBanner {
  277. return nil, r, fmt.Errorf("bytes did not contain a proper nebula Ed25519 private key banner")
  278. }
  279. if len(k.Bytes) != ed25519.PrivateKeySize {
  280. return nil, r, fmt.Errorf("key was not 64 bytes, is invalid ed25519 private key")
  281. }
  282. return k.Bytes, r, nil
  283. }
  284. // UnmarshalNebulaEncryptedData will unmarshal a protobuf byte representation of a nebula cert into its
  285. // protobuf-generated struct.
  286. func UnmarshalNebulaEncryptedData(b []byte) (*NebulaEncryptedData, error) {
  287. if len(b) == 0 {
  288. return nil, fmt.Errorf("nil byte array")
  289. }
  290. var rned RawNebulaEncryptedData
  291. err := proto.Unmarshal(b, &rned)
  292. if err != nil {
  293. return nil, err
  294. }
  295. if rned.EncryptionMetadata == nil {
  296. return nil, fmt.Errorf("encoded EncryptionMetadata was nil")
  297. }
  298. if rned.EncryptionMetadata.Argon2Parameters == nil {
  299. return nil, fmt.Errorf("encoded Argon2Parameters was nil")
  300. }
  301. params, err := unmarshalArgon2Parameters(rned.EncryptionMetadata.Argon2Parameters)
  302. if err != nil {
  303. return nil, err
  304. }
  305. ned := NebulaEncryptedData{
  306. EncryptionMetadata: NebulaEncryptionMetadata{
  307. EncryptionAlgorithm: rned.EncryptionMetadata.EncryptionAlgorithm,
  308. Argon2Parameters: *params,
  309. },
  310. Ciphertext: rned.Ciphertext,
  311. }
  312. return &ned, nil
  313. }
  314. func unmarshalArgon2Parameters(params *RawNebulaArgon2Parameters) (*Argon2Parameters, error) {
  315. if params.Version < math.MinInt32 || params.Version > math.MaxInt32 {
  316. return nil, fmt.Errorf("Argon2Parameters Version must be at least %d and no more than %d", math.MinInt32, math.MaxInt32)
  317. }
  318. if params.Memory <= 0 || params.Memory > math.MaxUint32 {
  319. return nil, fmt.Errorf("Argon2Parameters Memory must be be greater than 0 and no more than %d KiB", uint32(math.MaxUint32))
  320. }
  321. if params.Parallelism <= 0 || params.Parallelism > math.MaxUint8 {
  322. return nil, fmt.Errorf("Argon2Parameters Parallelism must be be greater than 0 and no more than %d", math.MaxUint8)
  323. }
  324. if params.Iterations <= 0 || params.Iterations > math.MaxUint32 {
  325. return nil, fmt.Errorf("-argon-iterations must be be greater than 0 and no more than %d", uint32(math.MaxUint32))
  326. }
  327. return &Argon2Parameters{
  328. version: rune(params.Version),
  329. Memory: uint32(params.Memory),
  330. Parallelism: uint8(params.Parallelism),
  331. Iterations: uint32(params.Iterations),
  332. salt: params.Salt,
  333. }, nil
  334. }
  335. // DecryptAndUnmarshalSigningPrivateKey will try to pem decode and decrypt an Ed25519/ECDSA private key with
  336. // the given passphrase, returning any other bytes b or an error on failure
  337. func DecryptAndUnmarshalSigningPrivateKey(passphrase, b []byte) (Curve, []byte, []byte, error) {
  338. var curve Curve
  339. k, r := pem.Decode(b)
  340. if k == nil {
  341. return curve, nil, r, fmt.Errorf("input did not contain a valid PEM encoded block")
  342. }
  343. switch k.Type {
  344. case EncryptedEd25519PrivateKeyBanner:
  345. curve = Curve_CURVE25519
  346. case EncryptedECDSAP256PrivateKeyBanner:
  347. curve = Curve_P256
  348. default:
  349. return curve, nil, r, fmt.Errorf("bytes did not contain a proper nebula encrypted Ed25519/ECDSA private key banner")
  350. }
  351. ned, err := UnmarshalNebulaEncryptedData(k.Bytes)
  352. if err != nil {
  353. return curve, nil, r, err
  354. }
  355. var bytes []byte
  356. switch ned.EncryptionMetadata.EncryptionAlgorithm {
  357. case "AES-256-GCM":
  358. bytes, err = aes256Decrypt(passphrase, &ned.EncryptionMetadata.Argon2Parameters, ned.Ciphertext)
  359. if err != nil {
  360. return curve, nil, r, err
  361. }
  362. default:
  363. return curve, nil, r, fmt.Errorf("unsupported encryption algorithm: %s", ned.EncryptionMetadata.EncryptionAlgorithm)
  364. }
  365. switch curve {
  366. case Curve_CURVE25519:
  367. if len(bytes) != ed25519.PrivateKeySize {
  368. return curve, nil, r, fmt.Errorf("key was not %d bytes, is invalid ed25519 private key", ed25519.PrivateKeySize)
  369. }
  370. case Curve_P256:
  371. if len(bytes) != 32 {
  372. return curve, nil, r, fmt.Errorf("key was not 32 bytes, is invalid ECDSA P256 private key")
  373. }
  374. }
  375. return curve, bytes, r, nil
  376. }
  377. func MarshalPublicKey(curve Curve, b []byte) []byte {
  378. switch curve {
  379. case Curve_CURVE25519:
  380. return pem.EncodeToMemory(&pem.Block{Type: X25519PublicKeyBanner, Bytes: b})
  381. case Curve_P256:
  382. return pem.EncodeToMemory(&pem.Block{Type: P256PublicKeyBanner, Bytes: b})
  383. default:
  384. return nil
  385. }
  386. }
  387. // MarshalX25519PublicKey is a simple helper to PEM encode an X25519 public key
  388. func MarshalX25519PublicKey(b []byte) []byte {
  389. return pem.EncodeToMemory(&pem.Block{Type: X25519PublicKeyBanner, Bytes: b})
  390. }
  391. // MarshalEd25519PublicKey is a simple helper to PEM encode an Ed25519 public key
  392. func MarshalEd25519PublicKey(key ed25519.PublicKey) []byte {
  393. return pem.EncodeToMemory(&pem.Block{Type: Ed25519PublicKeyBanner, Bytes: key})
  394. }
  395. func UnmarshalPublicKey(b []byte) ([]byte, []byte, Curve, error) {
  396. k, r := pem.Decode(b)
  397. if k == nil {
  398. return nil, r, 0, fmt.Errorf("input did not contain a valid PEM encoded block")
  399. }
  400. var expectedLen int
  401. var curve Curve
  402. switch k.Type {
  403. case X25519PublicKeyBanner:
  404. expectedLen = 32
  405. curve = Curve_CURVE25519
  406. case P256PublicKeyBanner:
  407. // Uncompressed
  408. expectedLen = 65
  409. curve = Curve_P256
  410. default:
  411. return nil, r, 0, fmt.Errorf("bytes did not contain a proper nebula public key banner")
  412. }
  413. if len(k.Bytes) != expectedLen {
  414. return nil, r, 0, fmt.Errorf("key was not %d bytes, is invalid %s public key", expectedLen, curve)
  415. }
  416. return k.Bytes, r, curve, nil
  417. }
  418. // UnmarshalX25519PublicKey will try to pem decode an X25519 public key, returning any other bytes b
  419. // or an error on failure
  420. func UnmarshalX25519PublicKey(b []byte) ([]byte, []byte, error) {
  421. k, r := pem.Decode(b)
  422. if k == nil {
  423. return nil, r, fmt.Errorf("input did not contain a valid PEM encoded block")
  424. }
  425. if k.Type != X25519PublicKeyBanner {
  426. return nil, r, fmt.Errorf("bytes did not contain a proper nebula X25519 public key banner")
  427. }
  428. if len(k.Bytes) != publicKeyLen {
  429. return nil, r, fmt.Errorf("key was not 32 bytes, is invalid X25519 public key")
  430. }
  431. return k.Bytes, r, nil
  432. }
  433. // UnmarshalEd25519PublicKey will try to pem decode an Ed25519 public key, returning any other bytes b
  434. // or an error on failure
  435. func UnmarshalEd25519PublicKey(b []byte) (ed25519.PublicKey, []byte, error) {
  436. k, r := pem.Decode(b)
  437. if k == nil {
  438. return nil, r, fmt.Errorf("input did not contain a valid PEM encoded block")
  439. }
  440. if k.Type != Ed25519PublicKeyBanner {
  441. return nil, r, fmt.Errorf("bytes did not contain a proper nebula Ed25519 public key banner")
  442. }
  443. if len(k.Bytes) != ed25519.PublicKeySize {
  444. return nil, r, fmt.Errorf("key was not 32 bytes, is invalid ed25519 public key")
  445. }
  446. return k.Bytes, r, nil
  447. }
  448. // Sign signs a nebula cert with the provided private key
  449. func (nc *NebulaCertificate) Sign(curve Curve, key []byte) error {
  450. if curve != nc.Details.Curve {
  451. return fmt.Errorf("curve in cert and private key supplied don't match")
  452. }
  453. b, err := proto.Marshal(nc.getRawDetails())
  454. if err != nil {
  455. return err
  456. }
  457. var sig []byte
  458. switch curve {
  459. case Curve_CURVE25519:
  460. signer := ed25519.PrivateKey(key)
  461. sig = ed25519.Sign(signer, b)
  462. case Curve_P256:
  463. signer := &ecdsa.PrivateKey{
  464. PublicKey: ecdsa.PublicKey{
  465. Curve: elliptic.P256(),
  466. },
  467. // ref: https://github.com/golang/go/blob/go1.19/src/crypto/x509/sec1.go#L95
  468. D: new(big.Int).SetBytes(key),
  469. }
  470. // ref: https://github.com/golang/go/blob/go1.19/src/crypto/x509/sec1.go#L119
  471. signer.X, signer.Y = signer.Curve.ScalarBaseMult(key)
  472. // We need to hash first for ECDSA
  473. // - https://pkg.go.dev/crypto/ecdsa#SignASN1
  474. hashed := sha256.Sum256(b)
  475. sig, err = ecdsa.SignASN1(rand.Reader, signer, hashed[:])
  476. if err != nil {
  477. return err
  478. }
  479. default:
  480. return fmt.Errorf("invalid curve: %s", nc.Details.Curve)
  481. }
  482. nc.Signature = sig
  483. return nil
  484. }
  485. // CheckSignature verifies the signature against the provided public key
  486. func (nc *NebulaCertificate) CheckSignature(key []byte) bool {
  487. b, err := proto.Marshal(nc.getRawDetails())
  488. if err != nil {
  489. return false
  490. }
  491. switch nc.Details.Curve {
  492. case Curve_CURVE25519:
  493. return ed25519.Verify(ed25519.PublicKey(key), b, nc.Signature)
  494. case Curve_P256:
  495. x, y := elliptic.Unmarshal(elliptic.P256(), key)
  496. pubKey := &ecdsa.PublicKey{Curve: elliptic.P256(), X: x, Y: y}
  497. hashed := sha256.Sum256(b)
  498. return ecdsa.VerifyASN1(pubKey, hashed[:], nc.Signature)
  499. default:
  500. return false
  501. }
  502. }
  503. // NOTE: This uses an internal cache that will not be invalidated automatically
  504. // if you manually change any fields in the NebulaCertificate.
  505. func (nc *NebulaCertificate) checkSignatureWithCache(key []byte, useCache bool) bool {
  506. if !useCache {
  507. return nc.CheckSignature(key)
  508. }
  509. if v := nc.signatureVerified.Load(); v != nil {
  510. return bytes.Equal(*v, key)
  511. }
  512. verified := nc.CheckSignature(key)
  513. if verified {
  514. keyCopy := make([]byte, len(key))
  515. copy(keyCopy, key)
  516. nc.signatureVerified.Store(&keyCopy)
  517. }
  518. return verified
  519. }
  520. // Expired will return true if the nebula cert is too young or too old compared to the provided time, otherwise false
  521. func (nc *NebulaCertificate) Expired(t time.Time) bool {
  522. return nc.Details.NotBefore.After(t) || nc.Details.NotAfter.Before(t)
  523. }
  524. // Verify will ensure a certificate is good in all respects (expiry, group membership, signature, cert blocklist, etc)
  525. func (nc *NebulaCertificate) Verify(t time.Time, ncp *NebulaCAPool) (bool, error) {
  526. return nc.verify(t, ncp, false)
  527. }
  528. // VerifyWithCache will ensure a certificate is good in all respects (expiry, group membership, signature, cert blocklist, etc)
  529. //
  530. // NOTE: This uses an internal cache that will not be invalidated automatically
  531. // if you manually change any fields in the NebulaCertificate.
  532. func (nc *NebulaCertificate) VerifyWithCache(t time.Time, ncp *NebulaCAPool) (bool, error) {
  533. return nc.verify(t, ncp, true)
  534. }
  535. // ResetCache resets the cache used by VerifyWithCache.
  536. func (nc *NebulaCertificate) ResetCache() {
  537. nc.sha256sum.Store(nil)
  538. nc.signatureVerified.Store(nil)
  539. }
  540. // Verify will ensure a certificate is good in all respects (expiry, group membership, signature, cert blocklist, etc)
  541. func (nc *NebulaCertificate) verify(t time.Time, ncp *NebulaCAPool, useCache bool) (bool, error) {
  542. if ncp.isBlocklistedWithCache(nc, useCache) {
  543. return false, ErrBlockListed
  544. }
  545. signer, err := ncp.GetCAForCert(nc)
  546. if err != nil {
  547. return false, err
  548. }
  549. if signer.Expired(t) {
  550. return false, ErrRootExpired
  551. }
  552. if nc.Expired(t) {
  553. return false, ErrExpired
  554. }
  555. if !nc.checkSignatureWithCache(signer.Details.PublicKey, useCache) {
  556. return false, ErrSignatureMismatch
  557. }
  558. if err := nc.CheckRootConstrains(signer); err != nil {
  559. return false, err
  560. }
  561. return true, nil
  562. }
  563. // CheckRootConstrains returns an error if the certificate violates constraints set on the root (groups, ips, subnets)
  564. func (nc *NebulaCertificate) CheckRootConstrains(signer *NebulaCertificate) error {
  565. // Make sure this cert wasn't valid before the root
  566. if signer.Details.NotAfter.Before(nc.Details.NotAfter) {
  567. return fmt.Errorf("certificate expires after signing certificate")
  568. }
  569. // Make sure this cert isn't valid after the root
  570. if signer.Details.NotBefore.After(nc.Details.NotBefore) {
  571. return fmt.Errorf("certificate is valid before the signing certificate")
  572. }
  573. // If the signer has a limited set of groups make sure the cert only contains a subset
  574. if len(signer.Details.InvertedGroups) > 0 {
  575. for _, g := range nc.Details.Groups {
  576. if _, ok := signer.Details.InvertedGroups[g]; !ok {
  577. return fmt.Errorf("certificate contained a group not present on the signing ca: %s", g)
  578. }
  579. }
  580. }
  581. // If the signer has a limited set of ip ranges to issue from make sure the cert only contains a subset
  582. if len(signer.Details.Ips) > 0 {
  583. for _, ip := range nc.Details.Ips {
  584. if !netMatch(ip, signer.Details.Ips) {
  585. return fmt.Errorf("certificate contained an ip assignment outside the limitations of the signing ca: %s", ip.String())
  586. }
  587. }
  588. }
  589. // If the signer has a limited set of subnet ranges to issue from make sure the cert only contains a subset
  590. if len(signer.Details.Subnets) > 0 {
  591. for _, subnet := range nc.Details.Subnets {
  592. if !netMatch(subnet, signer.Details.Subnets) {
  593. return fmt.Errorf("certificate contained a subnet assignment outside the limitations of the signing ca: %s", subnet)
  594. }
  595. }
  596. }
  597. return nil
  598. }
  599. // VerifyPrivateKey checks that the public key in the Nebula certificate and a supplied private key match
  600. func (nc *NebulaCertificate) VerifyPrivateKey(curve Curve, key []byte) error {
  601. if curve != nc.Details.Curve {
  602. return fmt.Errorf("curve in cert and private key supplied don't match")
  603. }
  604. if nc.Details.IsCA {
  605. switch curve {
  606. case Curve_CURVE25519:
  607. // the call to PublicKey below will panic slice bounds out of range otherwise
  608. if len(key) != ed25519.PrivateKeySize {
  609. return fmt.Errorf("key was not 64 bytes, is invalid ed25519 private key")
  610. }
  611. if !ed25519.PublicKey(nc.Details.PublicKey).Equal(ed25519.PrivateKey(key).Public()) {
  612. return fmt.Errorf("public key in cert and private key supplied don't match")
  613. }
  614. case Curve_P256:
  615. privkey, err := ecdh.P256().NewPrivateKey(key)
  616. if err != nil {
  617. return fmt.Errorf("cannot parse private key as P256")
  618. }
  619. pub := privkey.PublicKey().Bytes()
  620. if !bytes.Equal(pub, nc.Details.PublicKey) {
  621. return fmt.Errorf("public key in cert and private key supplied don't match")
  622. }
  623. default:
  624. return fmt.Errorf("invalid curve: %s", curve)
  625. }
  626. return nil
  627. }
  628. var pub []byte
  629. switch curve {
  630. case Curve_CURVE25519:
  631. var err error
  632. pub, err = curve25519.X25519(key, curve25519.Basepoint)
  633. if err != nil {
  634. return err
  635. }
  636. case Curve_P256:
  637. privkey, err := ecdh.P256().NewPrivateKey(key)
  638. if err != nil {
  639. return err
  640. }
  641. pub = privkey.PublicKey().Bytes()
  642. default:
  643. return fmt.Errorf("invalid curve: %s", curve)
  644. }
  645. if !bytes.Equal(pub, nc.Details.PublicKey) {
  646. return fmt.Errorf("public key in cert and private key supplied don't match")
  647. }
  648. return nil
  649. }
  650. // String will return a pretty printed representation of a nebula cert
  651. func (nc *NebulaCertificate) String() string {
  652. if nc == nil {
  653. return "NebulaCertificate {}\n"
  654. }
  655. s := "NebulaCertificate {\n"
  656. s += "\tDetails {\n"
  657. s += fmt.Sprintf("\t\tName: %v\n", nc.Details.Name)
  658. if len(nc.Details.Ips) > 0 {
  659. s += "\t\tIps: [\n"
  660. for _, ip := range nc.Details.Ips {
  661. s += fmt.Sprintf("\t\t\t%v\n", ip.String())
  662. }
  663. s += "\t\t]\n"
  664. } else {
  665. s += "\t\tIps: []\n"
  666. }
  667. if len(nc.Details.Subnets) > 0 {
  668. s += "\t\tSubnets: [\n"
  669. for _, ip := range nc.Details.Subnets {
  670. s += fmt.Sprintf("\t\t\t%v\n", ip.String())
  671. }
  672. s += "\t\t]\n"
  673. } else {
  674. s += "\t\tSubnets: []\n"
  675. }
  676. if len(nc.Details.Groups) > 0 {
  677. s += "\t\tGroups: [\n"
  678. for _, g := range nc.Details.Groups {
  679. s += fmt.Sprintf("\t\t\t\"%v\"\n", g)
  680. }
  681. s += "\t\t]\n"
  682. } else {
  683. s += "\t\tGroups: []\n"
  684. }
  685. s += fmt.Sprintf("\t\tNot before: %v\n", nc.Details.NotBefore)
  686. s += fmt.Sprintf("\t\tNot After: %v\n", nc.Details.NotAfter)
  687. s += fmt.Sprintf("\t\tIs CA: %v\n", nc.Details.IsCA)
  688. s += fmt.Sprintf("\t\tIssuer: %s\n", nc.Details.Issuer)
  689. s += fmt.Sprintf("\t\tPublic key: %x\n", nc.Details.PublicKey)
  690. s += fmt.Sprintf("\t\tCurve: %s\n", nc.Details.Curve)
  691. s += "\t}\n"
  692. fp, err := nc.Sha256Sum()
  693. if err == nil {
  694. s += fmt.Sprintf("\tFingerprint: %s\n", fp)
  695. }
  696. s += fmt.Sprintf("\tSignature: %x\n", nc.Signature)
  697. s += "}"
  698. return s
  699. }
  700. // getRawDetails marshals the raw details into protobuf ready struct
  701. func (nc *NebulaCertificate) getRawDetails() *RawNebulaCertificateDetails {
  702. rd := &RawNebulaCertificateDetails{
  703. Name: nc.Details.Name,
  704. Groups: nc.Details.Groups,
  705. NotBefore: nc.Details.NotBefore.Unix(),
  706. NotAfter: nc.Details.NotAfter.Unix(),
  707. PublicKey: make([]byte, len(nc.Details.PublicKey)),
  708. IsCA: nc.Details.IsCA,
  709. Curve: nc.Details.Curve,
  710. }
  711. for _, ipNet := range nc.Details.Ips {
  712. rd.Ips = append(rd.Ips, ip2int(ipNet.IP), ip2int(ipNet.Mask))
  713. }
  714. for _, ipNet := range nc.Details.Subnets {
  715. rd.Subnets = append(rd.Subnets, ip2int(ipNet.IP), ip2int(ipNet.Mask))
  716. }
  717. copy(rd.PublicKey, nc.Details.PublicKey[:])
  718. // I know, this is terrible
  719. rd.Issuer, _ = hex.DecodeString(nc.Details.Issuer)
  720. return rd
  721. }
  722. // Marshal will marshal a nebula cert into a protobuf byte array
  723. func (nc *NebulaCertificate) Marshal() ([]byte, error) {
  724. rc := RawNebulaCertificate{
  725. Details: nc.getRawDetails(),
  726. Signature: nc.Signature,
  727. }
  728. return proto.Marshal(&rc)
  729. }
  730. // MarshalToPEM will marshal a nebula cert into a protobuf byte array and pem encode the result
  731. func (nc *NebulaCertificate) MarshalToPEM() ([]byte, error) {
  732. b, err := nc.Marshal()
  733. if err != nil {
  734. return nil, err
  735. }
  736. return pem.EncodeToMemory(&pem.Block{Type: CertBanner, Bytes: b}), nil
  737. }
  738. // Sha256Sum calculates a sha-256 sum of the marshaled certificate
  739. func (nc *NebulaCertificate) Sha256Sum() (string, error) {
  740. b, err := nc.Marshal()
  741. if err != nil {
  742. return "", err
  743. }
  744. sum := sha256.Sum256(b)
  745. return hex.EncodeToString(sum[:]), nil
  746. }
  747. // NOTE: This uses an internal cache that will not be invalidated automatically
  748. // if you manually change any fields in the NebulaCertificate.
  749. func (nc *NebulaCertificate) sha256SumWithCache(useCache bool) (string, error) {
  750. if !useCache {
  751. return nc.Sha256Sum()
  752. }
  753. if s := nc.sha256sum.Load(); s != nil {
  754. return *s, nil
  755. }
  756. s, err := nc.Sha256Sum()
  757. if err != nil {
  758. return s, err
  759. }
  760. nc.sha256sum.Store(&s)
  761. return s, nil
  762. }
  763. func (nc *NebulaCertificate) MarshalJSON() ([]byte, error) {
  764. toString := func(ips []*net.IPNet) []string {
  765. s := []string{}
  766. for _, ip := range ips {
  767. s = append(s, ip.String())
  768. }
  769. return s
  770. }
  771. fp, _ := nc.Sha256Sum()
  772. jc := m{
  773. "details": m{
  774. "name": nc.Details.Name,
  775. "ips": toString(nc.Details.Ips),
  776. "subnets": toString(nc.Details.Subnets),
  777. "groups": nc.Details.Groups,
  778. "notBefore": nc.Details.NotBefore,
  779. "notAfter": nc.Details.NotAfter,
  780. "publicKey": fmt.Sprintf("%x", nc.Details.PublicKey),
  781. "isCa": nc.Details.IsCA,
  782. "issuer": nc.Details.Issuer,
  783. "curve": nc.Details.Curve.String(),
  784. },
  785. "fingerprint": fp,
  786. "signature": fmt.Sprintf("%x", nc.Signature),
  787. }
  788. return json.Marshal(jc)
  789. }
  790. //func (nc *NebulaCertificate) Copy() *NebulaCertificate {
  791. // r, err := nc.Marshal()
  792. // if err != nil {
  793. // //TODO
  794. // return nil
  795. // }
  796. //
  797. // c, err := UnmarshalNebulaCertificate(r)
  798. // return c
  799. //}
  800. func (nc *NebulaCertificate) Copy() *NebulaCertificate {
  801. c := &NebulaCertificate{
  802. Details: NebulaCertificateDetails{
  803. Name: nc.Details.Name,
  804. Groups: make([]string, len(nc.Details.Groups)),
  805. Ips: make([]*net.IPNet, len(nc.Details.Ips)),
  806. Subnets: make([]*net.IPNet, len(nc.Details.Subnets)),
  807. NotBefore: nc.Details.NotBefore,
  808. NotAfter: nc.Details.NotAfter,
  809. PublicKey: make([]byte, len(nc.Details.PublicKey)),
  810. IsCA: nc.Details.IsCA,
  811. Issuer: nc.Details.Issuer,
  812. InvertedGroups: make(map[string]struct{}, len(nc.Details.InvertedGroups)),
  813. },
  814. Signature: make([]byte, len(nc.Signature)),
  815. }
  816. copy(c.Signature, nc.Signature)
  817. copy(c.Details.Groups, nc.Details.Groups)
  818. copy(c.Details.PublicKey, nc.Details.PublicKey)
  819. for i, p := range nc.Details.Ips {
  820. c.Details.Ips[i] = &net.IPNet{
  821. IP: make(net.IP, len(p.IP)),
  822. Mask: make(net.IPMask, len(p.Mask)),
  823. }
  824. copy(c.Details.Ips[i].IP, p.IP)
  825. copy(c.Details.Ips[i].Mask, p.Mask)
  826. }
  827. for i, p := range nc.Details.Subnets {
  828. c.Details.Subnets[i] = &net.IPNet{
  829. IP: make(net.IP, len(p.IP)),
  830. Mask: make(net.IPMask, len(p.Mask)),
  831. }
  832. copy(c.Details.Subnets[i].IP, p.IP)
  833. copy(c.Details.Subnets[i].Mask, p.Mask)
  834. }
  835. for g := range nc.Details.InvertedGroups {
  836. c.Details.InvertedGroups[g] = struct{}{}
  837. }
  838. return c
  839. }
  840. func netMatch(certIp *net.IPNet, rootIps []*net.IPNet) bool {
  841. for _, net := range rootIps {
  842. if net.Contains(certIp.IP) && maskContains(net.Mask, certIp.Mask) {
  843. return true
  844. }
  845. }
  846. return false
  847. }
  848. func maskContains(caMask, certMask net.IPMask) bool {
  849. caM := maskTo4(caMask)
  850. cM := maskTo4(certMask)
  851. // Make sure forcing to ipv4 didn't nuke us
  852. if caM == nil || cM == nil {
  853. return false
  854. }
  855. // Make sure the cert mask is not greater than the ca mask
  856. for i := 0; i < len(caMask); i++ {
  857. if caM[i] > cM[i] {
  858. return false
  859. }
  860. }
  861. return true
  862. }
  863. func maskTo4(ip net.IPMask) net.IPMask {
  864. if len(ip) == net.IPv4len {
  865. return ip
  866. }
  867. if len(ip) == net.IPv6len && isZeros(ip[0:10]) && ip[10] == 0xff && ip[11] == 0xff {
  868. return ip[12:16]
  869. }
  870. return nil
  871. }
  872. func isZeros(b []byte) bool {
  873. for i := 0; i < len(b); i++ {
  874. if b[i] != 0 {
  875. return false
  876. }
  877. }
  878. return true
  879. }
  880. func ip2int(ip []byte) uint32 {
  881. if len(ip) == 16 {
  882. return binary.BigEndian.Uint32(ip[12:16])
  883. }
  884. return binary.BigEndian.Uint32(ip)
  885. }
  886. func int2ip(nn uint32) net.IP {
  887. ip := make(net.IP, net.IPv4len)
  888. binary.BigEndian.PutUint32(ip, nn)
  889. return ip
  890. }