cert.go 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958
  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. switch curve {
  356. case Curve_CURVE25519:
  357. if len(bytes) != ed25519.PrivateKeySize {
  358. return curve, nil, r, fmt.Errorf("key was not %d bytes, is invalid ed25519 private key", ed25519.PrivateKeySize)
  359. }
  360. case Curve_P256:
  361. if len(bytes) != 32 {
  362. return curve, nil, r, fmt.Errorf("key was not 32 bytes, is invalid ECDSA P256 private key")
  363. }
  364. }
  365. return curve, bytes, r, nil
  366. }
  367. func MarshalPublicKey(curve Curve, b []byte) []byte {
  368. switch curve {
  369. case Curve_CURVE25519:
  370. return pem.EncodeToMemory(&pem.Block{Type: X25519PublicKeyBanner, Bytes: b})
  371. case Curve_P256:
  372. return pem.EncodeToMemory(&pem.Block{Type: P256PublicKeyBanner, Bytes: b})
  373. default:
  374. return nil
  375. }
  376. }
  377. // MarshalX25519PublicKey is a simple helper to PEM encode an X25519 public key
  378. func MarshalX25519PublicKey(b []byte) []byte {
  379. return pem.EncodeToMemory(&pem.Block{Type: X25519PublicKeyBanner, Bytes: b})
  380. }
  381. // MarshalEd25519PublicKey is a simple helper to PEM encode an Ed25519 public key
  382. func MarshalEd25519PublicKey(key ed25519.PublicKey) []byte {
  383. return pem.EncodeToMemory(&pem.Block{Type: Ed25519PublicKeyBanner, Bytes: key})
  384. }
  385. func UnmarshalPublicKey(b []byte) ([]byte, []byte, Curve, error) {
  386. k, r := pem.Decode(b)
  387. if k == nil {
  388. return nil, r, 0, fmt.Errorf("input did not contain a valid PEM encoded block")
  389. }
  390. var expectedLen int
  391. var curve Curve
  392. switch k.Type {
  393. case X25519PublicKeyBanner:
  394. expectedLen = 32
  395. curve = Curve_CURVE25519
  396. case P256PublicKeyBanner:
  397. // Uncompressed
  398. expectedLen = 65
  399. curve = Curve_P256
  400. default:
  401. return nil, r, 0, fmt.Errorf("bytes did not contain a proper nebula public key banner")
  402. }
  403. if len(k.Bytes) != expectedLen {
  404. return nil, r, 0, fmt.Errorf("key was not %d bytes, is invalid %s public key", expectedLen, curve)
  405. }
  406. return k.Bytes, r, curve, nil
  407. }
  408. // UnmarshalX25519PublicKey will try to pem decode an X25519 public key, returning any other bytes b
  409. // or an error on failure
  410. func UnmarshalX25519PublicKey(b []byte) ([]byte, []byte, error) {
  411. k, r := pem.Decode(b)
  412. if k == nil {
  413. return nil, r, fmt.Errorf("input did not contain a valid PEM encoded block")
  414. }
  415. if k.Type != X25519PublicKeyBanner {
  416. return nil, r, fmt.Errorf("bytes did not contain a proper nebula X25519 public key banner")
  417. }
  418. if len(k.Bytes) != publicKeyLen {
  419. return nil, r, fmt.Errorf("key was not 32 bytes, is invalid X25519 public key")
  420. }
  421. return k.Bytes, r, nil
  422. }
  423. // UnmarshalEd25519PublicKey will try to pem decode an Ed25519 public key, returning any other bytes b
  424. // or an error on failure
  425. func UnmarshalEd25519PublicKey(b []byte) (ed25519.PublicKey, []byte, error) {
  426. k, r := pem.Decode(b)
  427. if k == nil {
  428. return nil, r, fmt.Errorf("input did not contain a valid PEM encoded block")
  429. }
  430. if k.Type != Ed25519PublicKeyBanner {
  431. return nil, r, fmt.Errorf("bytes did not contain a proper nebula Ed25519 public key banner")
  432. }
  433. if len(k.Bytes) != ed25519.PublicKeySize {
  434. return nil, r, fmt.Errorf("key was not 32 bytes, is invalid ed25519 public key")
  435. }
  436. return k.Bytes, r, nil
  437. }
  438. // Sign signs a nebula cert with the provided private key
  439. func (nc *NebulaCertificate) Sign(curve Curve, key []byte) error {
  440. if curve != nc.Details.Curve {
  441. return fmt.Errorf("curve in cert and private key supplied don't match")
  442. }
  443. b, err := proto.Marshal(nc.getRawDetails())
  444. if err != nil {
  445. return err
  446. }
  447. var sig []byte
  448. switch curve {
  449. case Curve_CURVE25519:
  450. signer := ed25519.PrivateKey(key)
  451. sig = ed25519.Sign(signer, b)
  452. case Curve_P256:
  453. signer := &ecdsa.PrivateKey{
  454. PublicKey: ecdsa.PublicKey{
  455. Curve: elliptic.P256(),
  456. },
  457. // ref: https://github.com/golang/go/blob/go1.19/src/crypto/x509/sec1.go#L95
  458. D: new(big.Int).SetBytes(key),
  459. }
  460. // ref: https://github.com/golang/go/blob/go1.19/src/crypto/x509/sec1.go#L119
  461. signer.X, signer.Y = signer.Curve.ScalarBaseMult(key)
  462. // We need to hash first for ECDSA
  463. // - https://pkg.go.dev/crypto/ecdsa#SignASN1
  464. hashed := sha256.Sum256(b)
  465. sig, err = ecdsa.SignASN1(rand.Reader, signer, hashed[:])
  466. if err != nil {
  467. return err
  468. }
  469. default:
  470. return fmt.Errorf("invalid curve: %s", nc.Details.Curve)
  471. }
  472. nc.Signature = sig
  473. return nil
  474. }
  475. // CheckSignature verifies the signature against the provided public key
  476. func (nc *NebulaCertificate) CheckSignature(key []byte) bool {
  477. b, err := proto.Marshal(nc.getRawDetails())
  478. if err != nil {
  479. return false
  480. }
  481. switch nc.Details.Curve {
  482. case Curve_CURVE25519:
  483. return ed25519.Verify(ed25519.PublicKey(key), b, nc.Signature)
  484. case Curve_P256:
  485. x, y := elliptic.Unmarshal(elliptic.P256(), key)
  486. pubKey := &ecdsa.PublicKey{Curve: elliptic.P256(), X: x, Y: y}
  487. hashed := sha256.Sum256(b)
  488. return ecdsa.VerifyASN1(pubKey, hashed[:], nc.Signature)
  489. default:
  490. return false
  491. }
  492. }
  493. // Expired will return true if the nebula cert is too young or too old compared to the provided time, otherwise false
  494. func (nc *NebulaCertificate) Expired(t time.Time) bool {
  495. return nc.Details.NotBefore.After(t) || nc.Details.NotAfter.Before(t)
  496. }
  497. // Verify will ensure a certificate is good in all respects (expiry, group membership, signature, cert blocklist, etc)
  498. func (nc *NebulaCertificate) Verify(t time.Time, ncp *NebulaCAPool) (bool, error) {
  499. if ncp.IsBlocklisted(nc) {
  500. return false, ErrBlockListed
  501. }
  502. signer, err := ncp.GetCAForCert(nc)
  503. if err != nil {
  504. return false, err
  505. }
  506. if signer.Expired(t) {
  507. return false, ErrRootExpired
  508. }
  509. if nc.Expired(t) {
  510. return false, ErrExpired
  511. }
  512. if !nc.CheckSignature(signer.Details.PublicKey) {
  513. return false, ErrSignatureMismatch
  514. }
  515. if err := nc.CheckRootConstrains(signer); err != nil {
  516. return false, err
  517. }
  518. return true, nil
  519. }
  520. // CheckRootConstrains returns an error if the certificate violates constraints set on the root (groups, ips, subnets)
  521. func (nc *NebulaCertificate) CheckRootConstrains(signer *NebulaCertificate) error {
  522. // Make sure this cert wasn't valid before the root
  523. if signer.Details.NotAfter.Before(nc.Details.NotAfter) {
  524. return fmt.Errorf("certificate expires after signing certificate")
  525. }
  526. // Make sure this cert isn't valid after the root
  527. if signer.Details.NotBefore.After(nc.Details.NotBefore) {
  528. return fmt.Errorf("certificate is valid before the signing certificate")
  529. }
  530. // If the signer has a limited set of groups make sure the cert only contains a subset
  531. if len(signer.Details.InvertedGroups) > 0 {
  532. for _, g := range nc.Details.Groups {
  533. if _, ok := signer.Details.InvertedGroups[g]; !ok {
  534. return fmt.Errorf("certificate contained a group not present on the signing ca: %s", g)
  535. }
  536. }
  537. }
  538. // If the signer has a limited set of ip ranges to issue from make sure the cert only contains a subset
  539. if len(signer.Details.Ips) > 0 {
  540. for _, ip := range nc.Details.Ips {
  541. if !netMatch(ip, signer.Details.Ips) {
  542. return fmt.Errorf("certificate contained an ip assignment outside the limitations of the signing ca: %s", ip.String())
  543. }
  544. }
  545. }
  546. // If the signer has a limited set of subnet ranges to issue from make sure the cert only contains a subset
  547. if len(signer.Details.Subnets) > 0 {
  548. for _, subnet := range nc.Details.Subnets {
  549. if !netMatch(subnet, signer.Details.Subnets) {
  550. return fmt.Errorf("certificate contained a subnet assignment outside the limitations of the signing ca: %s", subnet)
  551. }
  552. }
  553. }
  554. return nil
  555. }
  556. // VerifyPrivateKey checks that the public key in the Nebula certificate and a supplied private key match
  557. func (nc *NebulaCertificate) VerifyPrivateKey(curve Curve, key []byte) error {
  558. if curve != nc.Details.Curve {
  559. return fmt.Errorf("curve in cert and private key supplied don't match")
  560. }
  561. if nc.Details.IsCA {
  562. switch curve {
  563. case Curve_CURVE25519:
  564. // the call to PublicKey below will panic slice bounds out of range otherwise
  565. if len(key) != ed25519.PrivateKeySize {
  566. return fmt.Errorf("key was not 64 bytes, is invalid ed25519 private key")
  567. }
  568. if !ed25519.PublicKey(nc.Details.PublicKey).Equal(ed25519.PrivateKey(key).Public()) {
  569. return fmt.Errorf("public key in cert and private key supplied don't match")
  570. }
  571. case Curve_P256:
  572. privkey, err := ecdh.P256().NewPrivateKey(key)
  573. if err != nil {
  574. return fmt.Errorf("cannot parse private key as P256")
  575. }
  576. pub := privkey.PublicKey().Bytes()
  577. if !bytes.Equal(pub, nc.Details.PublicKey) {
  578. return fmt.Errorf("public key in cert and private key supplied don't match")
  579. }
  580. default:
  581. return fmt.Errorf("invalid curve: %s", curve)
  582. }
  583. return nil
  584. }
  585. var pub []byte
  586. switch curve {
  587. case Curve_CURVE25519:
  588. var err error
  589. pub, err = curve25519.X25519(key, curve25519.Basepoint)
  590. if err != nil {
  591. return err
  592. }
  593. case Curve_P256:
  594. privkey, err := ecdh.P256().NewPrivateKey(key)
  595. if err != nil {
  596. return err
  597. }
  598. pub = privkey.PublicKey().Bytes()
  599. default:
  600. return fmt.Errorf("invalid curve: %s", curve)
  601. }
  602. if !bytes.Equal(pub, nc.Details.PublicKey) {
  603. return fmt.Errorf("public key in cert and private key supplied don't match")
  604. }
  605. return nil
  606. }
  607. // String will return a pretty printed representation of a nebula cert
  608. func (nc *NebulaCertificate) String() string {
  609. if nc == nil {
  610. return "NebulaCertificate {}\n"
  611. }
  612. s := "NebulaCertificate {\n"
  613. s += "\tDetails {\n"
  614. s += fmt.Sprintf("\t\tName: %v\n", nc.Details.Name)
  615. if len(nc.Details.Ips) > 0 {
  616. s += "\t\tIps: [\n"
  617. for _, ip := range nc.Details.Ips {
  618. s += fmt.Sprintf("\t\t\t%v\n", ip.String())
  619. }
  620. s += "\t\t]\n"
  621. } else {
  622. s += "\t\tIps: []\n"
  623. }
  624. if len(nc.Details.Subnets) > 0 {
  625. s += "\t\tSubnets: [\n"
  626. for _, ip := range nc.Details.Subnets {
  627. s += fmt.Sprintf("\t\t\t%v\n", ip.String())
  628. }
  629. s += "\t\t]\n"
  630. } else {
  631. s += "\t\tSubnets: []\n"
  632. }
  633. if len(nc.Details.Groups) > 0 {
  634. s += "\t\tGroups: [\n"
  635. for _, g := range nc.Details.Groups {
  636. s += fmt.Sprintf("\t\t\t\"%v\"\n", g)
  637. }
  638. s += "\t\t]\n"
  639. } else {
  640. s += "\t\tGroups: []\n"
  641. }
  642. s += fmt.Sprintf("\t\tNot before: %v\n", nc.Details.NotBefore)
  643. s += fmt.Sprintf("\t\tNot After: %v\n", nc.Details.NotAfter)
  644. s += fmt.Sprintf("\t\tIs CA: %v\n", nc.Details.IsCA)
  645. s += fmt.Sprintf("\t\tIssuer: %s\n", nc.Details.Issuer)
  646. s += fmt.Sprintf("\t\tPublic key: %x\n", nc.Details.PublicKey)
  647. s += fmt.Sprintf("\t\tCurve: %s\n", nc.Details.Curve)
  648. s += "\t}\n"
  649. fp, err := nc.Sha256Sum()
  650. if err == nil {
  651. s += fmt.Sprintf("\tFingerprint: %s\n", fp)
  652. }
  653. s += fmt.Sprintf("\tSignature: %x\n", nc.Signature)
  654. s += "}"
  655. return s
  656. }
  657. // getRawDetails marshals the raw details into protobuf ready struct
  658. func (nc *NebulaCertificate) getRawDetails() *RawNebulaCertificateDetails {
  659. rd := &RawNebulaCertificateDetails{
  660. Name: nc.Details.Name,
  661. Groups: nc.Details.Groups,
  662. NotBefore: nc.Details.NotBefore.Unix(),
  663. NotAfter: nc.Details.NotAfter.Unix(),
  664. PublicKey: make([]byte, len(nc.Details.PublicKey)),
  665. IsCA: nc.Details.IsCA,
  666. Curve: nc.Details.Curve,
  667. }
  668. for _, ipNet := range nc.Details.Ips {
  669. rd.Ips = append(rd.Ips, ip2int(ipNet.IP), ip2int(ipNet.Mask))
  670. }
  671. for _, ipNet := range nc.Details.Subnets {
  672. rd.Subnets = append(rd.Subnets, ip2int(ipNet.IP), ip2int(ipNet.Mask))
  673. }
  674. copy(rd.PublicKey, nc.Details.PublicKey[:])
  675. // I know, this is terrible
  676. rd.Issuer, _ = hex.DecodeString(nc.Details.Issuer)
  677. return rd
  678. }
  679. // Marshal will marshal a nebula cert into a protobuf byte array
  680. func (nc *NebulaCertificate) Marshal() ([]byte, error) {
  681. rc := RawNebulaCertificate{
  682. Details: nc.getRawDetails(),
  683. Signature: nc.Signature,
  684. }
  685. return proto.Marshal(&rc)
  686. }
  687. // MarshalToPEM will marshal a nebula cert into a protobuf byte array and pem encode the result
  688. func (nc *NebulaCertificate) MarshalToPEM() ([]byte, error) {
  689. b, err := nc.Marshal()
  690. if err != nil {
  691. return nil, err
  692. }
  693. return pem.EncodeToMemory(&pem.Block{Type: CertBanner, Bytes: b}), nil
  694. }
  695. // Sha256Sum calculates a sha-256 sum of the marshaled certificate
  696. func (nc *NebulaCertificate) Sha256Sum() (string, error) {
  697. b, err := nc.Marshal()
  698. if err != nil {
  699. return "", err
  700. }
  701. sum := sha256.Sum256(b)
  702. return hex.EncodeToString(sum[:]), nil
  703. }
  704. func (nc *NebulaCertificate) MarshalJSON() ([]byte, error) {
  705. toString := func(ips []*net.IPNet) []string {
  706. s := []string{}
  707. for _, ip := range ips {
  708. s = append(s, ip.String())
  709. }
  710. return s
  711. }
  712. fp, _ := nc.Sha256Sum()
  713. jc := m{
  714. "details": m{
  715. "name": nc.Details.Name,
  716. "ips": toString(nc.Details.Ips),
  717. "subnets": toString(nc.Details.Subnets),
  718. "groups": nc.Details.Groups,
  719. "notBefore": nc.Details.NotBefore,
  720. "notAfter": nc.Details.NotAfter,
  721. "publicKey": fmt.Sprintf("%x", nc.Details.PublicKey),
  722. "isCa": nc.Details.IsCA,
  723. "issuer": nc.Details.Issuer,
  724. "curve": nc.Details.Curve.String(),
  725. },
  726. "fingerprint": fp,
  727. "signature": fmt.Sprintf("%x", nc.Signature),
  728. }
  729. return json.Marshal(jc)
  730. }
  731. //func (nc *NebulaCertificate) Copy() *NebulaCertificate {
  732. // r, err := nc.Marshal()
  733. // if err != nil {
  734. // //TODO
  735. // return nil
  736. // }
  737. //
  738. // c, err := UnmarshalNebulaCertificate(r)
  739. // return c
  740. //}
  741. func (nc *NebulaCertificate) Copy() *NebulaCertificate {
  742. c := &NebulaCertificate{
  743. Details: NebulaCertificateDetails{
  744. Name: nc.Details.Name,
  745. Groups: make([]string, len(nc.Details.Groups)),
  746. Ips: make([]*net.IPNet, len(nc.Details.Ips)),
  747. Subnets: make([]*net.IPNet, len(nc.Details.Subnets)),
  748. NotBefore: nc.Details.NotBefore,
  749. NotAfter: nc.Details.NotAfter,
  750. PublicKey: make([]byte, len(nc.Details.PublicKey)),
  751. IsCA: nc.Details.IsCA,
  752. Issuer: nc.Details.Issuer,
  753. InvertedGroups: make(map[string]struct{}, len(nc.Details.InvertedGroups)),
  754. },
  755. Signature: make([]byte, len(nc.Signature)),
  756. }
  757. copy(c.Signature, nc.Signature)
  758. copy(c.Details.Groups, nc.Details.Groups)
  759. copy(c.Details.PublicKey, nc.Details.PublicKey)
  760. for i, p := range nc.Details.Ips {
  761. c.Details.Ips[i] = &net.IPNet{
  762. IP: make(net.IP, len(p.IP)),
  763. Mask: make(net.IPMask, len(p.Mask)),
  764. }
  765. copy(c.Details.Ips[i].IP, p.IP)
  766. copy(c.Details.Ips[i].Mask, p.Mask)
  767. }
  768. for i, p := range nc.Details.Subnets {
  769. c.Details.Subnets[i] = &net.IPNet{
  770. IP: make(net.IP, len(p.IP)),
  771. Mask: make(net.IPMask, len(p.Mask)),
  772. }
  773. copy(c.Details.Subnets[i].IP, p.IP)
  774. copy(c.Details.Subnets[i].Mask, p.Mask)
  775. }
  776. for g := range nc.Details.InvertedGroups {
  777. c.Details.InvertedGroups[g] = struct{}{}
  778. }
  779. return c
  780. }
  781. func netMatch(certIp *net.IPNet, rootIps []*net.IPNet) bool {
  782. for _, net := range rootIps {
  783. if net.Contains(certIp.IP) && maskContains(net.Mask, certIp.Mask) {
  784. return true
  785. }
  786. }
  787. return false
  788. }
  789. func maskContains(caMask, certMask net.IPMask) bool {
  790. caM := maskTo4(caMask)
  791. cM := maskTo4(certMask)
  792. // Make sure forcing to ipv4 didn't nuke us
  793. if caM == nil || cM == nil {
  794. return false
  795. }
  796. // Make sure the cert mask is not greater than the ca mask
  797. for i := 0; i < len(caMask); i++ {
  798. if caM[i] > cM[i] {
  799. return false
  800. }
  801. }
  802. return true
  803. }
  804. func maskTo4(ip net.IPMask) net.IPMask {
  805. if len(ip) == net.IPv4len {
  806. return ip
  807. }
  808. if len(ip) == net.IPv6len && isZeros(ip[0:10]) && ip[10] == 0xff && ip[11] == 0xff {
  809. return ip[12:16]
  810. }
  811. return nil
  812. }
  813. func isZeros(b []byte) bool {
  814. for i := 0; i < len(b); i++ {
  815. if b[i] != 0 {
  816. return false
  817. }
  818. }
  819. return true
  820. }
  821. func ip2int(ip []byte) uint32 {
  822. if len(ip) == 16 {
  823. return binary.BigEndian.Uint32(ip[12:16])
  824. }
  825. return binary.BigEndian.Uint32(ip)
  826. }
  827. func int2ip(nn uint32) net.IP {
  828. ip := make(net.IP, net.IPv4len)
  829. binary.BigEndian.PutUint32(ip, nn)
  830. return ip
  831. }