cert.go 28 KB

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