cert.go 30 KB

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