cert_test.go 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695
  1. package cert
  2. import (
  3. "crypto/ecdh"
  4. "crypto/ecdsa"
  5. "crypto/elliptic"
  6. "crypto/rand"
  7. "fmt"
  8. "io"
  9. "net/netip"
  10. "testing"
  11. "time"
  12. "github.com/slackhq/nebula/test"
  13. "github.com/stretchr/testify/assert"
  14. "golang.org/x/crypto/curve25519"
  15. "golang.org/x/crypto/ed25519"
  16. )
  17. func TestMarshalingNebulaCertificate(t *testing.T) {
  18. before := time.Now().Add(time.Second * -60).Round(time.Second)
  19. after := time.Now().Add(time.Second * 60).Round(time.Second)
  20. pubKey := []byte("1234567890abcedfghij1234567890ab")
  21. nc := certificateV1{
  22. details: detailsV1{
  23. Name: "testing",
  24. Ips: []netip.Prefix{
  25. mustParsePrefixUnmapped("10.1.1.1/24"),
  26. mustParsePrefixUnmapped("10.1.1.2/16"),
  27. },
  28. Subnets: []netip.Prefix{
  29. mustParsePrefixUnmapped("9.1.1.2/24"),
  30. mustParsePrefixUnmapped("9.1.1.3/16"),
  31. },
  32. Groups: []string{"test-group1", "test-group2", "test-group3"},
  33. NotBefore: before,
  34. NotAfter: after,
  35. PublicKey: pubKey,
  36. IsCA: false,
  37. Issuer: "1234567890abcedfghij1234567890ab",
  38. },
  39. signature: []byte("1234567890abcedfghij1234567890ab"),
  40. }
  41. b, err := nc.Marshal()
  42. assert.Nil(t, err)
  43. //t.Log("Cert size:", len(b))
  44. nc2, err := unmarshalCertificateV1(b, true)
  45. assert.Nil(t, err)
  46. assert.Equal(t, nc.signature, nc2.Signature())
  47. assert.Equal(t, nc.details.Name, nc2.Name())
  48. assert.Equal(t, nc.details.NotBefore, nc2.NotBefore())
  49. assert.Equal(t, nc.details.NotAfter, nc2.NotAfter())
  50. assert.Equal(t, nc.details.PublicKey, nc2.PublicKey())
  51. assert.Equal(t, nc.details.IsCA, nc2.IsCA())
  52. assert.Equal(t, nc.details.Ips, nc2.Networks())
  53. assert.Equal(t, nc.details.Subnets, nc2.UnsafeNetworks())
  54. assert.Equal(t, nc.details.Groups, nc2.Groups())
  55. }
  56. //func TestNebulaCertificate_Sign(t *testing.T) {
  57. // before := time.Now().Add(time.Second * -60).Round(time.Second)
  58. // after := time.Now().Add(time.Second * 60).Round(time.Second)
  59. // pubKey := []byte("1234567890abcedfghij1234567890ab")
  60. //
  61. // nc := certificateV1{
  62. // details: detailsV1{
  63. // Name: "testing",
  64. // Ips: []netip.Prefix{
  65. // mustParsePrefixUnmapped("10.1.1.1/24"),
  66. // mustParsePrefixUnmapped("10.1.1.2/16"),
  67. // //TODO: netip cant do it
  68. // //{IP: net.ParseIP("10.1.1.3"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
  69. // },
  70. // Subnets: []netip.Prefix{
  71. // //TODO: netip cant do it
  72. // //{IP: net.ParseIP("9.1.1.1"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
  73. // mustParsePrefixUnmapped("9.1.1.2/24"),
  74. // mustParsePrefixUnmapped("9.1.1.3/24"),
  75. // },
  76. // Groups: []string{"test-group1", "test-group2", "test-group3"},
  77. // NotBefore: before,
  78. // NotAfter: after,
  79. // PublicKey: pubKey,
  80. // IsCA: false,
  81. // Issuer: "1234567890abcedfghij1234567890ab",
  82. // },
  83. // }
  84. //
  85. // pub, priv, err := ed25519.GenerateKey(rand.Reader)
  86. // assert.Nil(t, err)
  87. // assert.False(t, nc.CheckSignature(pub))
  88. // assert.Nil(t, nc.Sign(Curve_CURVE25519, priv))
  89. // assert.True(t, nc.CheckSignature(pub))
  90. //
  91. // _, err = nc.Marshal()
  92. // assert.Nil(t, err)
  93. // //t.Log("Cert size:", len(b))
  94. //}
  95. //func TestNebulaCertificate_SignP256(t *testing.T) {
  96. // before := time.Now().Add(time.Second * -60).Round(time.Second)
  97. // after := time.Now().Add(time.Second * 60).Round(time.Second)
  98. // pubKey := []byte("01234567890abcedfghij1234567890ab1234567890abcedfghij1234567890ab")
  99. //
  100. // nc := certificateV1{
  101. // details: detailsV1{
  102. // Name: "testing",
  103. // Ips: []netip.Prefix{
  104. // mustParsePrefixUnmapped("10.1.1.1/24"),
  105. // mustParsePrefixUnmapped("10.1.1.2/16"),
  106. // //TODO: netip no can do
  107. // //{IP: net.ParseIP("10.1.1.3"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
  108. // },
  109. // Subnets: []netip.Prefix{
  110. // //TODO: netip bad
  111. // //{IP: net.ParseIP("9.1.1.1"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
  112. // mustParsePrefixUnmapped("9.1.1.2/24"),
  113. // mustParsePrefixUnmapped("9.1.1.3/16"),
  114. // },
  115. // Groups: []string{"test-group1", "test-group2", "test-group3"},
  116. // NotBefore: before,
  117. // NotAfter: after,
  118. // PublicKey: pubKey,
  119. // IsCA: false,
  120. // Curve: Curve_P256,
  121. // Issuer: "1234567890abcedfghij1234567890ab",
  122. // },
  123. // }
  124. //
  125. // priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  126. // pub := elliptic.Marshal(elliptic.P256(), priv.PublicKey.X, priv.PublicKey.Y)
  127. // rawPriv := priv.D.FillBytes(make([]byte, 32))
  128. //
  129. // assert.Nil(t, err)
  130. // assert.False(t, nc.CheckSignature(pub))
  131. // assert.Nil(t, nc.Sign(Curve_P256, rawPriv))
  132. // assert.True(t, nc.CheckSignature(pub))
  133. //
  134. // _, err = nc.Marshal()
  135. // assert.Nil(t, err)
  136. // //t.Log("Cert size:", len(b))
  137. //}
  138. func TestNebulaCertificate_Expired(t *testing.T) {
  139. nc := certificateV1{
  140. details: detailsV1{
  141. NotBefore: time.Now().Add(time.Second * -60).Round(time.Second),
  142. NotAfter: time.Now().Add(time.Second * 60).Round(time.Second),
  143. },
  144. }
  145. assert.True(t, nc.Expired(time.Now().Add(time.Hour)))
  146. assert.True(t, nc.Expired(time.Now().Add(-time.Hour)))
  147. assert.False(t, nc.Expired(time.Now()))
  148. }
  149. func TestNebulaCertificate_MarshalJSON(t *testing.T) {
  150. time.Local = time.UTC
  151. pubKey := []byte("1234567890abcedfghij1234567890ab")
  152. nc := certificateV1{
  153. details: detailsV1{
  154. Name: "testing",
  155. Ips: []netip.Prefix{
  156. mustParsePrefixUnmapped("10.1.1.1/24"),
  157. mustParsePrefixUnmapped("10.1.1.2/16"),
  158. },
  159. Subnets: []netip.Prefix{
  160. mustParsePrefixUnmapped("9.1.1.2/24"),
  161. mustParsePrefixUnmapped("9.1.1.3/16"),
  162. },
  163. Groups: []string{"test-group1", "test-group2", "test-group3"},
  164. NotBefore: time.Date(1, 0, 0, 1, 0, 0, 0, time.UTC),
  165. NotAfter: time.Date(1, 0, 0, 2, 0, 0, 0, time.UTC),
  166. PublicKey: pubKey,
  167. IsCA: false,
  168. Issuer: "1234567890abcedfghij1234567890ab",
  169. },
  170. signature: []byte("1234567890abcedfghij1234567890ab"),
  171. }
  172. b, err := nc.MarshalJSON()
  173. assert.Nil(t, err)
  174. assert.Equal(
  175. t,
  176. "{\"details\":{\"curve\":\"CURVE25519\",\"groups\":[\"test-group1\",\"test-group2\",\"test-group3\"],\"ips\":[\"10.1.1.1/24\",\"10.1.1.2/16\"],\"isCa\":false,\"issuer\":\"1234567890abcedfghij1234567890ab\",\"name\":\"testing\",\"notAfter\":\"0000-11-30T02:00:00Z\",\"notBefore\":\"0000-11-30T01:00:00Z\",\"publicKey\":\"313233343536373839306162636564666768696a313233343536373839306162\",\"subnets\":[\"9.1.1.2/24\",\"9.1.1.3/16\"]},\"fingerprint\":\"3944c53d4267a229295b56cb2d27d459164c010ac97d655063ba421e0670f4ba\",\"signature\":\"313233343536373839306162636564666768696a313233343536373839306162\"}",
  177. string(b),
  178. )
  179. }
  180. func TestNebulaCertificate_Verify(t *testing.T) {
  181. ca, _, caKey, err := newTestCaCert(time.Now(), time.Now().Add(10*time.Minute), nil, nil, nil)
  182. assert.Nil(t, err)
  183. c, _, _, err := newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), nil, nil, nil)
  184. assert.Nil(t, err)
  185. caPool := NewCAPool()
  186. assert.NoError(t, caPool.AddCA(ca))
  187. f, err := c.Fingerprint()
  188. assert.Nil(t, err)
  189. caPool.BlocklistFingerprint(f)
  190. _, err = caPool.VerifyCertificate(time.Now(), c)
  191. assert.EqualError(t, err, "certificate is in the block list")
  192. caPool.ResetCertBlocklist()
  193. _, err = caPool.VerifyCertificate(time.Now(), c)
  194. assert.Nil(t, err)
  195. _, err = caPool.VerifyCertificate(time.Now().Add(time.Hour*1000), c)
  196. assert.EqualError(t, err, "root certificate is expired")
  197. c, _, _, err = newTestCert(ca, caKey, time.Time{}, time.Time{}, nil, nil, nil)
  198. assert.EqualError(t, err, "certificate is valid before the signing certificate")
  199. // Test group assertion
  200. ca, _, caKey, err = newTestCaCert(time.Now(), time.Now().Add(10*time.Minute), nil, nil, []string{"test1", "test2"})
  201. assert.Nil(t, err)
  202. caPem, err := ca.MarshalPEM()
  203. assert.Nil(t, err)
  204. caPool = NewCAPool()
  205. b, err := caPool.AddCAFromPEM(caPem)
  206. assert.NoError(t, err)
  207. assert.Empty(t, b)
  208. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), nil, nil, []string{"test1", "bad"})
  209. assert.EqualError(t, err, "certificate contained a group not present on the signing ca: bad")
  210. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), nil, nil, []string{"test1"})
  211. assert.Nil(t, err)
  212. _, err = caPool.VerifyCertificate(time.Now(), c)
  213. assert.Nil(t, err)
  214. }
  215. func TestNebulaCertificate_VerifyP256(t *testing.T) {
  216. ca, _, caKey, err := newTestCaCertP256(time.Now(), time.Now().Add(10*time.Minute), nil, nil, nil)
  217. assert.Nil(t, err)
  218. c, _, _, err := newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), nil, nil, nil)
  219. assert.Nil(t, err)
  220. caPool := NewCAPool()
  221. assert.NoError(t, caPool.AddCA(ca))
  222. f, err := c.Fingerprint()
  223. assert.Nil(t, err)
  224. caPool.BlocklistFingerprint(f)
  225. _, err = caPool.VerifyCertificate(time.Now(), c)
  226. assert.EqualError(t, err, "certificate is in the block list")
  227. caPool.ResetCertBlocklist()
  228. _, err = caPool.VerifyCertificate(time.Now(), c)
  229. assert.Nil(t, err)
  230. _, err = caPool.VerifyCertificate(time.Now().Add(time.Hour*1000), c)
  231. assert.EqualError(t, err, "root certificate is expired")
  232. c, _, _, err = newTestCert(ca, caKey, time.Time{}, time.Time{}, nil, nil, nil)
  233. assert.EqualError(t, err, "certificate is valid before the signing certificate")
  234. // Test group assertion
  235. ca, _, caKey, err = newTestCaCertP256(time.Now(), time.Now().Add(10*time.Minute), nil, nil, []string{"test1", "test2"})
  236. assert.Nil(t, err)
  237. caPem, err := ca.MarshalPEM()
  238. assert.Nil(t, err)
  239. caPool = NewCAPool()
  240. b, err := caPool.AddCAFromPEM(caPem)
  241. assert.NoError(t, err)
  242. assert.Empty(t, b)
  243. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), nil, nil, []string{"test1", "bad"})
  244. assert.EqualError(t, err, "certificate contained a group not present on the signing ca: bad")
  245. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), nil, nil, []string{"test1"})
  246. assert.Nil(t, err)
  247. _, err = caPool.VerifyCertificate(time.Now(), c)
  248. assert.Nil(t, err)
  249. }
  250. func TestNebulaCertificate_Verify_IPs(t *testing.T) {
  251. caIp1 := mustParsePrefixUnmapped("10.0.0.0/16")
  252. caIp2 := mustParsePrefixUnmapped("192.168.0.0/24")
  253. ca, _, caKey, err := newTestCaCert(time.Now(), time.Now().Add(10*time.Minute), []netip.Prefix{caIp1, caIp2}, nil, []string{"test"})
  254. assert.Nil(t, err)
  255. caPem, err := ca.MarshalPEM()
  256. assert.Nil(t, err)
  257. caPool := NewCAPool()
  258. b, err := caPool.AddCAFromPEM(caPem)
  259. assert.NoError(t, err)
  260. assert.Empty(t, b)
  261. // ip is outside the network
  262. cIp1 := mustParsePrefixUnmapped("10.1.0.0/24")
  263. cIp2 := mustParsePrefixUnmapped("192.168.0.1/16")
  264. c, _, _, err := newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []netip.Prefix{cIp1, cIp2}, nil, []string{"test"})
  265. assert.EqualError(t, err, "certificate contained a network assignment outside the limitations of the signing ca: 10.1.0.0/24")
  266. // ip is outside the network reversed order of above
  267. cIp1 = mustParsePrefixUnmapped("192.168.0.1/24")
  268. cIp2 = mustParsePrefixUnmapped("10.1.0.0/24")
  269. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []netip.Prefix{cIp1, cIp2}, nil, []string{"test"})
  270. assert.EqualError(t, err, "certificate contained a network assignment outside the limitations of the signing ca: 10.1.0.0/24")
  271. // ip is within the network but mask is outside
  272. cIp1 = mustParsePrefixUnmapped("10.0.1.0/15")
  273. cIp2 = mustParsePrefixUnmapped("192.168.0.1/24")
  274. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []netip.Prefix{cIp1, cIp2}, nil, []string{"test"})
  275. assert.EqualError(t, err, "certificate contained a network assignment outside the limitations of the signing ca: 10.0.1.0/15")
  276. // ip is within the network but mask is outside reversed order of above
  277. cIp1 = mustParsePrefixUnmapped("192.168.0.1/24")
  278. cIp2 = mustParsePrefixUnmapped("10.0.1.0/15")
  279. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []netip.Prefix{cIp1, cIp2}, nil, []string{"test"})
  280. assert.EqualError(t, err, "certificate contained a network assignment outside the limitations of the signing ca: 10.0.1.0/15")
  281. // ip and mask are within the network
  282. cIp1 = mustParsePrefixUnmapped("10.0.1.0/16")
  283. cIp2 = mustParsePrefixUnmapped("192.168.0.1/25")
  284. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []netip.Prefix{cIp1, cIp2}, nil, []string{"test"})
  285. assert.Nil(t, err)
  286. _, err = caPool.VerifyCertificate(time.Now(), c)
  287. assert.Nil(t, err)
  288. // Exact matches
  289. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []netip.Prefix{caIp1, caIp2}, nil, []string{"test"})
  290. assert.Nil(t, err)
  291. _, err = caPool.VerifyCertificate(time.Now(), c)
  292. assert.Nil(t, err)
  293. // Exact matches reversed
  294. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []netip.Prefix{caIp2, caIp1}, nil, []string{"test"})
  295. assert.Nil(t, err)
  296. _, err = caPool.VerifyCertificate(time.Now(), c)
  297. assert.Nil(t, err)
  298. // Exact matches reversed with just 1
  299. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []netip.Prefix{caIp1}, nil, []string{"test"})
  300. assert.Nil(t, err)
  301. _, err = caPool.VerifyCertificate(time.Now(), c)
  302. assert.Nil(t, err)
  303. }
  304. func TestNebulaCertificate_Verify_Subnets(t *testing.T) {
  305. caIp1 := mustParsePrefixUnmapped("10.0.0.0/16")
  306. caIp2 := mustParsePrefixUnmapped("192.168.0.0/24")
  307. ca, _, caKey, err := newTestCaCert(time.Now(), time.Now().Add(10*time.Minute), nil, []netip.Prefix{caIp1, caIp2}, []string{"test"})
  308. assert.Nil(t, err)
  309. caPem, err := ca.MarshalPEM()
  310. assert.Nil(t, err)
  311. caPool := NewCAPool()
  312. b, err := caPool.AddCAFromPEM(caPem)
  313. assert.NoError(t, err)
  314. assert.Empty(t, b)
  315. // ip is outside the network
  316. cIp1 := mustParsePrefixUnmapped("10.1.0.0/24")
  317. cIp2 := mustParsePrefixUnmapped("192.168.0.1/16")
  318. c, _, _, err := newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), nil, []netip.Prefix{cIp1, cIp2}, []string{"test"})
  319. assert.EqualError(t, err, "certificate contained an unsafe network assignment outside the limitations of the signing ca: 10.1.0.0/24")
  320. // ip is outside the network reversed order of above
  321. cIp1 = mustParsePrefixUnmapped("192.168.0.1/24")
  322. cIp2 = mustParsePrefixUnmapped("10.1.0.0/24")
  323. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), nil, []netip.Prefix{cIp1, cIp2}, []string{"test"})
  324. assert.EqualError(t, err, "certificate contained an unsafe network assignment outside the limitations of the signing ca: 10.1.0.0/24")
  325. // ip is within the network but mask is outside
  326. cIp1 = mustParsePrefixUnmapped("10.0.1.0/15")
  327. cIp2 = mustParsePrefixUnmapped("192.168.0.1/24")
  328. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), nil, []netip.Prefix{cIp1, cIp2}, []string{"test"})
  329. assert.EqualError(t, err, "certificate contained an unsafe network assignment outside the limitations of the signing ca: 10.0.1.0/15")
  330. // ip is within the network but mask is outside reversed order of above
  331. cIp1 = mustParsePrefixUnmapped("192.168.0.1/24")
  332. cIp2 = mustParsePrefixUnmapped("10.0.1.0/15")
  333. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), nil, []netip.Prefix{cIp1, cIp2}, []string{"test"})
  334. assert.EqualError(t, err, "certificate contained an unsafe network assignment outside the limitations of the signing ca: 10.0.1.0/15")
  335. // ip and mask are within the network
  336. cIp1 = mustParsePrefixUnmapped("10.0.1.0/16")
  337. cIp2 = mustParsePrefixUnmapped("192.168.0.1/25")
  338. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), nil, []netip.Prefix{cIp1, cIp2}, []string{"test"})
  339. assert.Nil(t, err)
  340. _, err = caPool.VerifyCertificate(time.Now(), c)
  341. assert.Nil(t, err)
  342. // Exact matches
  343. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), nil, []netip.Prefix{caIp1, caIp2}, []string{"test"})
  344. assert.Nil(t, err)
  345. _, err = caPool.VerifyCertificate(time.Now(), c)
  346. assert.Nil(t, err)
  347. // Exact matches reversed
  348. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), nil, []netip.Prefix{caIp2, caIp1}, []string{"test"})
  349. assert.Nil(t, err)
  350. _, err = caPool.VerifyCertificate(time.Now(), c)
  351. assert.Nil(t, err)
  352. // Exact matches reversed with just 1
  353. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), nil, []netip.Prefix{caIp1}, []string{"test"})
  354. assert.Nil(t, err)
  355. _, err = caPool.VerifyCertificate(time.Now(), c)
  356. assert.Nil(t, err)
  357. }
  358. func TestNebulaCertificate_VerifyPrivateKey(t *testing.T) {
  359. ca, _, caKey, err := newTestCaCert(time.Time{}, time.Time{}, nil, nil, nil)
  360. assert.Nil(t, err)
  361. err = ca.VerifyPrivateKey(Curve_CURVE25519, caKey)
  362. assert.Nil(t, err)
  363. _, _, caKey2, err := newTestCaCert(time.Time{}, time.Time{}, nil, nil, nil)
  364. assert.Nil(t, err)
  365. err = ca.VerifyPrivateKey(Curve_CURVE25519, caKey2)
  366. assert.NotNil(t, err)
  367. c, _, priv, err := newTestCert(ca, caKey, time.Time{}, time.Time{}, nil, nil, nil)
  368. err = c.VerifyPrivateKey(Curve_CURVE25519, priv)
  369. assert.Nil(t, err)
  370. _, priv2 := x25519Keypair()
  371. err = c.VerifyPrivateKey(Curve_CURVE25519, priv2)
  372. assert.NotNil(t, err)
  373. }
  374. func TestNebulaCertificate_VerifyPrivateKeyP256(t *testing.T) {
  375. ca, _, caKey, err := newTestCaCertP256(time.Time{}, time.Time{}, nil, nil, nil)
  376. assert.Nil(t, err)
  377. err = ca.VerifyPrivateKey(Curve_P256, caKey)
  378. assert.Nil(t, err)
  379. _, _, caKey2, err := newTestCaCertP256(time.Time{}, time.Time{}, nil, nil, nil)
  380. assert.Nil(t, err)
  381. err = ca.VerifyPrivateKey(Curve_P256, caKey2)
  382. assert.NotNil(t, err)
  383. c, _, priv, err := newTestCert(ca, caKey, time.Time{}, time.Time{}, nil, nil, nil)
  384. err = c.VerifyPrivateKey(Curve_P256, priv)
  385. assert.Nil(t, err)
  386. _, priv2 := p256Keypair()
  387. err = c.VerifyPrivateKey(Curve_P256, priv2)
  388. assert.NotNil(t, err)
  389. }
  390. func appendByteSlices(b ...[]byte) []byte {
  391. retSlice := []byte{}
  392. for _, v := range b {
  393. retSlice = append(retSlice, v...)
  394. }
  395. return retSlice
  396. }
  397. // Ensure that upgrading the protobuf library does not change how certificates
  398. // are marshalled, since this would break signature verification
  399. //TODO: since netip cant represent 255.0.255.0 netmask we can't verify the old certs are ok
  400. //func TestMarshalingNebulaCertificateConsistency(t *testing.T) {
  401. // before := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
  402. // after := time.Date(2017, time.January, 18, 28, 40, 0, 0, time.UTC)
  403. // pubKey := []byte("1234567890abcedfghij1234567890ab")
  404. //
  405. // nc := certificateV1{
  406. // details: detailsV1{
  407. // Name: "testing",
  408. // Ips: []netip.Prefix{
  409. // mustParsePrefixUnmapped("10.1.1.1/24"),
  410. // mustParsePrefixUnmapped("10.1.1.2/16"),
  411. // //TODO: netip bad
  412. // //{IP: net.ParseIP("10.1.1.3"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
  413. // },
  414. // Subnets: []netip.Prefix{
  415. // //TODO: netip bad
  416. // //{IP: net.ParseIP("9.1.1.1"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
  417. // mustParsePrefixUnmapped("9.1.1.2/24"),
  418. // mustParsePrefixUnmapped("9.1.1.3/16"),
  419. // },
  420. // Groups: []string{"test-group1", "test-group2", "test-group3"},
  421. // NotBefore: before,
  422. // NotAfter: after,
  423. // PublicKey: pubKey,
  424. // IsCA: false,
  425. // Issuer: "1234567890abcedfghij1234567890ab",
  426. // },
  427. // signature: []byte("1234567890abcedfghij1234567890ab"),
  428. // }
  429. //
  430. // b, err := nc.Marshal()
  431. // assert.Nil(t, err)
  432. // //t.Log("Cert size:", len(b))
  433. // assert.Equal(t, "0aa2010a0774657374696e67121b8182845080feffff0f828284508080fcff0f8382845080fe83f80f1a1b8182844880fe83f80f8282844880feffff0f838284488080fcff0f220b746573742d67726f757031220b746573742d67726f757032220b746573742d67726f75703328f0e0e7d70430a08681c4053a20313233343536373839306162636564666768696a3132333435363738393061624a081234567890abcedf1220313233343536373839306162636564666768696a313233343536373839306162", fmt.Sprintf("%x", b))
  434. //
  435. // b, err = proto.Marshal(nc.getRawDetails())
  436. // assert.Nil(t, err)
  437. // //t.Log("Raw cert size:", len(b))
  438. // assert.Equal(t, "0a0774657374696e67121b8182845080feffff0f828284508080fcff0f8382845080fe83f80f1a1b8182844880fe83f80f8282844880feffff0f838284488080fcff0f220b746573742d67726f757031220b746573742d67726f757032220b746573742d67726f75703328f0e0e7d70430a08681c4053a20313233343536373839306162636564666768696a3132333435363738393061624a081234567890abcedf", fmt.Sprintf("%x", b))
  439. //}
  440. func TestNebulaCertificate_Copy(t *testing.T) {
  441. ca, _, caKey, err := newTestCaCert(time.Now(), time.Now().Add(10*time.Minute), nil, nil, nil)
  442. assert.Nil(t, err)
  443. c, _, _, err := newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), nil, nil, nil)
  444. assert.Nil(t, err)
  445. cc := c.Copy()
  446. test.AssertDeepCopyEqual(t, c, cc)
  447. }
  448. func TestUnmarshalNebulaCertificate(t *testing.T) {
  449. // Test that we don't panic with an invalid certificate (#332)
  450. data := []byte("\x98\x00\x00")
  451. _, err := unmarshalCertificateV1(data, true)
  452. assert.EqualError(t, err, "encoded Details was nil")
  453. }
  454. func newTestCaCert(before, after time.Time, ips, subnets []netip.Prefix, groups []string) (Certificate, []byte, []byte, error) {
  455. pub, priv, err := ed25519.GenerateKey(rand.Reader)
  456. if before.IsZero() {
  457. before = time.Now().Add(time.Second * -60).Round(time.Second)
  458. }
  459. if after.IsZero() {
  460. after = time.Now().Add(time.Second * 60).Round(time.Second)
  461. }
  462. tbs := &TBSCertificate{
  463. Version: Version1,
  464. Name: "test ca",
  465. IsCA: true,
  466. NotBefore: time.Unix(before.Unix(), 0),
  467. NotAfter: time.Unix(after.Unix(), 0),
  468. PublicKey: pub,
  469. }
  470. if len(ips) > 0 {
  471. tbs.Networks = ips
  472. }
  473. if len(subnets) > 0 {
  474. tbs.UnsafeNetworks = subnets
  475. }
  476. if len(groups) > 0 {
  477. tbs.Groups = groups
  478. }
  479. nc, err := tbs.Sign(nil, Curve_CURVE25519, priv)
  480. if err != nil {
  481. return nil, nil, nil, err
  482. }
  483. return nc, pub, priv, nil
  484. }
  485. func newTestCaCertP256(before, after time.Time, ips, subnets []netip.Prefix, groups []string) (Certificate, []byte, []byte, error) {
  486. priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  487. pub := elliptic.Marshal(elliptic.P256(), priv.PublicKey.X, priv.PublicKey.Y)
  488. rawPriv := priv.D.FillBytes(make([]byte, 32))
  489. if before.IsZero() {
  490. before = time.Now().Add(time.Second * -60).Round(time.Second)
  491. }
  492. if after.IsZero() {
  493. after = time.Now().Add(time.Second * 60).Round(time.Second)
  494. }
  495. tbs := &TBSCertificate{
  496. Version: Version1,
  497. Name: "test ca",
  498. IsCA: true,
  499. NotBefore: time.Unix(before.Unix(), 0),
  500. NotAfter: time.Unix(after.Unix(), 0),
  501. PublicKey: pub,
  502. Curve: Curve_P256,
  503. }
  504. if len(ips) > 0 {
  505. tbs.Networks = ips
  506. }
  507. if len(subnets) > 0 {
  508. tbs.UnsafeNetworks = subnets
  509. }
  510. if len(groups) > 0 {
  511. tbs.Groups = groups
  512. }
  513. nc, err := tbs.Sign(nil, Curve_P256, rawPriv)
  514. if err != nil {
  515. return nil, nil, nil, err
  516. }
  517. return nc, pub, rawPriv, nil
  518. }
  519. func newTestCert(ca Certificate, key []byte, before, after time.Time, ips, subnets []netip.Prefix, groups []string) (Certificate, []byte, []byte, error) {
  520. if before.IsZero() {
  521. before = time.Now().Add(time.Second * -60).Round(time.Second)
  522. }
  523. if after.IsZero() {
  524. after = time.Now().Add(time.Second * 60).Round(time.Second)
  525. }
  526. if len(groups) == 0 {
  527. groups = []string{"test-group1", "test-group2", "test-group3"}
  528. }
  529. if len(ips) == 0 {
  530. ips = []netip.Prefix{
  531. mustParsePrefixUnmapped("10.1.1.1/24"),
  532. mustParsePrefixUnmapped("10.1.1.2/16"),
  533. }
  534. }
  535. if len(subnets) == 0 {
  536. subnets = []netip.Prefix{
  537. mustParsePrefixUnmapped("9.1.1.2/24"),
  538. mustParsePrefixUnmapped("9.1.1.3/16"),
  539. }
  540. }
  541. var pub, rawPriv []byte
  542. switch ca.Curve() {
  543. case Curve_CURVE25519:
  544. pub, rawPriv = x25519Keypair()
  545. case Curve_P256:
  546. pub, rawPriv = p256Keypair()
  547. default:
  548. return nil, nil, nil, fmt.Errorf("unknown curve: %v", ca.Curve())
  549. }
  550. tbs := &TBSCertificate{
  551. Version: Version1,
  552. Name: "testing",
  553. Networks: ips,
  554. UnsafeNetworks: subnets,
  555. Groups: groups,
  556. IsCA: false,
  557. NotBefore: time.Unix(before.Unix(), 0),
  558. NotAfter: time.Unix(after.Unix(), 0),
  559. PublicKey: pub,
  560. Curve: ca.Curve(),
  561. }
  562. nc, err := tbs.Sign(ca, ca.Curve(), key)
  563. if err != nil {
  564. return nil, nil, nil, err
  565. }
  566. return nc, pub, rawPriv, nil
  567. }
  568. func x25519Keypair() ([]byte, []byte) {
  569. privkey := make([]byte, 32)
  570. if _, err := io.ReadFull(rand.Reader, privkey); err != nil {
  571. panic(err)
  572. }
  573. pubkey, err := curve25519.X25519(privkey, curve25519.Basepoint)
  574. if err != nil {
  575. panic(err)
  576. }
  577. return pubkey, privkey
  578. }
  579. func p256Keypair() ([]byte, []byte) {
  580. privkey, err := ecdh.P256().GenerateKey(rand.Reader)
  581. if err != nil {
  582. panic(err)
  583. }
  584. pubkey := privkey.PublicKey()
  585. return pubkey.Bytes(), privkey.Bytes()
  586. }
  587. func mustParsePrefixUnmapped(s string) netip.Prefix {
  588. prefix := netip.MustParsePrefix(s)
  589. return netip.PrefixFrom(prefix.Addr().Unmap(), prefix.Bits())
  590. }