cert_test.go 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230
  1. package cert
  2. import (
  3. "crypto/ecdh"
  4. "crypto/ecdsa"
  5. "crypto/elliptic"
  6. "crypto/rand"
  7. "fmt"
  8. "io"
  9. "net"
  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. "google.golang.org/protobuf/proto"
  17. )
  18. func TestMarshalingNebulaCertificate(t *testing.T) {
  19. before := time.Now().Add(time.Second * -60).Round(time.Second)
  20. after := time.Now().Add(time.Second * 60).Round(time.Second)
  21. pubKey := []byte("1234567890abcedfghij1234567890ab")
  22. nc := NebulaCertificate{
  23. Details: NebulaCertificateDetails{
  24. Name: "testing",
  25. Ips: []*net.IPNet{
  26. {IP: net.ParseIP("10.1.1.1"), Mask: net.IPMask(net.ParseIP("255.255.255.0"))},
  27. {IP: net.ParseIP("10.1.1.2"), Mask: net.IPMask(net.ParseIP("255.255.0.0"))},
  28. {IP: net.ParseIP("10.1.1.3"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
  29. },
  30. Subnets: []*net.IPNet{
  31. {IP: net.ParseIP("9.1.1.1"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
  32. {IP: net.ParseIP("9.1.1.2"), Mask: net.IPMask(net.ParseIP("255.255.255.0"))},
  33. {IP: net.ParseIP("9.1.1.3"), Mask: net.IPMask(net.ParseIP("255.255.0.0"))},
  34. },
  35. Groups: []string{"test-group1", "test-group2", "test-group3"},
  36. NotBefore: before,
  37. NotAfter: after,
  38. PublicKey: pubKey,
  39. IsCA: false,
  40. Issuer: "1234567890abcedfghij1234567890ab",
  41. },
  42. Signature: []byte("1234567890abcedfghij1234567890ab"),
  43. }
  44. b, err := nc.Marshal()
  45. assert.Nil(t, err)
  46. //t.Log("Cert size:", len(b))
  47. nc2, err := UnmarshalNebulaCertificate(b)
  48. assert.Nil(t, err)
  49. assert.Equal(t, nc.Signature, nc2.Signature)
  50. assert.Equal(t, nc.Details.Name, nc2.Details.Name)
  51. assert.Equal(t, nc.Details.NotBefore, nc2.Details.NotBefore)
  52. assert.Equal(t, nc.Details.NotAfter, nc2.Details.NotAfter)
  53. assert.Equal(t, nc.Details.PublicKey, nc2.Details.PublicKey)
  54. assert.Equal(t, nc.Details.IsCA, nc2.Details.IsCA)
  55. // IP byte arrays can be 4 or 16 in length so we have to go this route
  56. assert.Equal(t, len(nc.Details.Ips), len(nc2.Details.Ips))
  57. for i, wIp := range nc.Details.Ips {
  58. assert.Equal(t, wIp.String(), nc2.Details.Ips[i].String())
  59. }
  60. assert.Equal(t, len(nc.Details.Subnets), len(nc2.Details.Subnets))
  61. for i, wIp := range nc.Details.Subnets {
  62. assert.Equal(t, wIp.String(), nc2.Details.Subnets[i].String())
  63. }
  64. assert.EqualValues(t, nc.Details.Groups, nc2.Details.Groups)
  65. }
  66. func TestNebulaCertificate_Sign(t *testing.T) {
  67. before := time.Now().Add(time.Second * -60).Round(time.Second)
  68. after := time.Now().Add(time.Second * 60).Round(time.Second)
  69. pubKey := []byte("1234567890abcedfghij1234567890ab")
  70. nc := NebulaCertificate{
  71. Details: NebulaCertificateDetails{
  72. Name: "testing",
  73. Ips: []*net.IPNet{
  74. {IP: net.ParseIP("10.1.1.1"), Mask: net.IPMask(net.ParseIP("255.255.255.0"))},
  75. {IP: net.ParseIP("10.1.1.2"), Mask: net.IPMask(net.ParseIP("255.255.0.0"))},
  76. {IP: net.ParseIP("10.1.1.3"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
  77. },
  78. Subnets: []*net.IPNet{
  79. {IP: net.ParseIP("9.1.1.1"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
  80. {IP: net.ParseIP("9.1.1.2"), Mask: net.IPMask(net.ParseIP("255.255.255.0"))},
  81. {IP: net.ParseIP("9.1.1.3"), Mask: net.IPMask(net.ParseIP("255.255.0.0"))},
  82. },
  83. Groups: []string{"test-group1", "test-group2", "test-group3"},
  84. NotBefore: before,
  85. NotAfter: after,
  86. PublicKey: pubKey,
  87. IsCA: false,
  88. Issuer: "1234567890abcedfghij1234567890ab",
  89. },
  90. }
  91. pub, priv, err := ed25519.GenerateKey(rand.Reader)
  92. assert.Nil(t, err)
  93. assert.False(t, nc.CheckSignature(pub))
  94. assert.Nil(t, nc.Sign(Curve_CURVE25519, priv))
  95. assert.True(t, nc.CheckSignature(pub))
  96. _, err = nc.Marshal()
  97. assert.Nil(t, err)
  98. //t.Log("Cert size:", len(b))
  99. }
  100. func TestNebulaCertificate_SignP256(t *testing.T) {
  101. before := time.Now().Add(time.Second * -60).Round(time.Second)
  102. after := time.Now().Add(time.Second * 60).Round(time.Second)
  103. pubKey := []byte("01234567890abcedfghij1234567890ab1234567890abcedfghij1234567890ab")
  104. nc := NebulaCertificate{
  105. Details: NebulaCertificateDetails{
  106. Name: "testing",
  107. Ips: []*net.IPNet{
  108. {IP: net.ParseIP("10.1.1.1"), Mask: net.IPMask(net.ParseIP("255.255.255.0"))},
  109. {IP: net.ParseIP("10.1.1.2"), Mask: net.IPMask(net.ParseIP("255.255.0.0"))},
  110. {IP: net.ParseIP("10.1.1.3"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
  111. },
  112. Subnets: []*net.IPNet{
  113. {IP: net.ParseIP("9.1.1.1"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
  114. {IP: net.ParseIP("9.1.1.2"), Mask: net.IPMask(net.ParseIP("255.255.255.0"))},
  115. {IP: net.ParseIP("9.1.1.3"), Mask: net.IPMask(net.ParseIP("255.255.0.0"))},
  116. },
  117. Groups: []string{"test-group1", "test-group2", "test-group3"},
  118. NotBefore: before,
  119. NotAfter: after,
  120. PublicKey: pubKey,
  121. IsCA: false,
  122. Curve: Curve_P256,
  123. Issuer: "1234567890abcedfghij1234567890ab",
  124. },
  125. }
  126. priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  127. pub := elliptic.Marshal(elliptic.P256(), priv.PublicKey.X, priv.PublicKey.Y)
  128. rawPriv := priv.D.FillBytes(make([]byte, 32))
  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. _, err = nc.Marshal()
  134. assert.Nil(t, err)
  135. //t.Log("Cert size:", len(b))
  136. }
  137. func TestNebulaCertificate_Expired(t *testing.T) {
  138. nc := NebulaCertificate{
  139. Details: NebulaCertificateDetails{
  140. NotBefore: time.Now().Add(time.Second * -60).Round(time.Second),
  141. NotAfter: time.Now().Add(time.Second * 60).Round(time.Second),
  142. },
  143. }
  144. assert.True(t, nc.Expired(time.Now().Add(time.Hour)))
  145. assert.True(t, nc.Expired(time.Now().Add(-time.Hour)))
  146. assert.False(t, nc.Expired(time.Now()))
  147. }
  148. func TestNebulaCertificate_MarshalJSON(t *testing.T) {
  149. time.Local = time.UTC
  150. pubKey := []byte("1234567890abcedfghij1234567890ab")
  151. nc := NebulaCertificate{
  152. Details: NebulaCertificateDetails{
  153. Name: "testing",
  154. Ips: []*net.IPNet{
  155. {IP: net.ParseIP("10.1.1.1"), Mask: net.IPMask(net.ParseIP("255.255.255.0"))},
  156. {IP: net.ParseIP("10.1.1.2"), Mask: net.IPMask(net.ParseIP("255.255.0.0"))},
  157. {IP: net.ParseIP("10.1.1.3"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
  158. },
  159. Subnets: []*net.IPNet{
  160. {IP: net.ParseIP("9.1.1.1"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
  161. {IP: net.ParseIP("9.1.1.2"), Mask: net.IPMask(net.ParseIP("255.255.255.0"))},
  162. {IP: net.ParseIP("9.1.1.3"), Mask: net.IPMask(net.ParseIP("255.255.0.0"))},
  163. },
  164. Groups: []string{"test-group1", "test-group2", "test-group3"},
  165. NotBefore: time.Date(1, 0, 0, 1, 0, 0, 0, time.UTC),
  166. NotAfter: time.Date(1, 0, 0, 2, 0, 0, 0, time.UTC),
  167. PublicKey: pubKey,
  168. IsCA: false,
  169. Issuer: "1234567890abcedfghij1234567890ab",
  170. },
  171. Signature: []byte("1234567890abcedfghij1234567890ab"),
  172. }
  173. b, err := nc.MarshalJSON()
  174. assert.Nil(t, err)
  175. assert.Equal(
  176. t,
  177. "{\"details\":{\"curve\":\"CURVE25519\",\"groups\":[\"test-group1\",\"test-group2\",\"test-group3\"],\"ips\":[\"10.1.1.1/24\",\"10.1.1.2/16\",\"10.1.1.3/ff00ff00\"],\"isCa\":false,\"issuer\":\"1234567890abcedfghij1234567890ab\",\"name\":\"testing\",\"notAfter\":\"0000-11-30T02:00:00Z\",\"notBefore\":\"0000-11-30T01:00:00Z\",\"publicKey\":\"313233343536373839306162636564666768696a313233343536373839306162\",\"subnets\":[\"9.1.1.1/ff00ff00\",\"9.1.1.2/24\",\"9.1.1.3/16\"]},\"fingerprint\":\"26cb1c30ad7872c804c166b5150fa372f437aa3856b04edb4334b4470ec728e4\",\"signature\":\"313233343536373839306162636564666768696a313233343536373839306162\"}",
  178. string(b),
  179. )
  180. }
  181. func TestNebulaCertificate_Verify(t *testing.T) {
  182. ca, _, caKey, err := newTestCaCert(time.Now(), time.Now().Add(10*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{})
  183. assert.Nil(t, err)
  184. c, _, _, err := newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{})
  185. assert.Nil(t, err)
  186. h, err := ca.Sha256Sum()
  187. assert.Nil(t, err)
  188. caPool := NewCAPool()
  189. caPool.CAs[h] = ca
  190. f, err := c.Sha256Sum()
  191. assert.Nil(t, err)
  192. caPool.BlocklistFingerprint(f)
  193. v, err := c.Verify(time.Now(), caPool)
  194. assert.False(t, v)
  195. assert.EqualError(t, err, "certificate is in the block list")
  196. caPool.ResetCertBlocklist()
  197. v, err = c.Verify(time.Now(), caPool)
  198. assert.True(t, v)
  199. assert.Nil(t, err)
  200. v, err = c.Verify(time.Now().Add(time.Hour*1000), caPool)
  201. assert.False(t, v)
  202. assert.EqualError(t, err, "root certificate is expired")
  203. c, _, _, err = newTestCert(ca, caKey, time.Time{}, time.Time{}, []*net.IPNet{}, []*net.IPNet{}, []string{})
  204. assert.Nil(t, err)
  205. v, err = c.Verify(time.Now().Add(time.Minute*6), caPool)
  206. assert.False(t, v)
  207. assert.EqualError(t, err, "certificate is expired")
  208. // Test group assertion
  209. ca, _, caKey, err = newTestCaCert(time.Now(), time.Now().Add(10*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{"test1", "test2"})
  210. assert.Nil(t, err)
  211. caPem, err := ca.MarshalToPEM()
  212. assert.Nil(t, err)
  213. caPool = NewCAPool()
  214. caPool.AddCACertificate(caPem)
  215. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{"test1", "bad"})
  216. assert.Nil(t, err)
  217. v, err = c.Verify(time.Now(), caPool)
  218. assert.False(t, v)
  219. assert.EqualError(t, err, "certificate contained a group not present on the signing ca: bad")
  220. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{"test1"})
  221. assert.Nil(t, err)
  222. v, err = c.Verify(time.Now(), caPool)
  223. assert.True(t, v)
  224. assert.Nil(t, err)
  225. }
  226. func TestNebulaCertificate_VerifyP256(t *testing.T) {
  227. ca, _, caKey, err := newTestCaCertP256(time.Now(), time.Now().Add(10*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{})
  228. assert.Nil(t, err)
  229. c, _, _, err := newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{})
  230. assert.Nil(t, err)
  231. h, err := ca.Sha256Sum()
  232. assert.Nil(t, err)
  233. caPool := NewCAPool()
  234. caPool.CAs[h] = ca
  235. f, err := c.Sha256Sum()
  236. assert.Nil(t, err)
  237. caPool.BlocklistFingerprint(f)
  238. v, err := c.Verify(time.Now(), caPool)
  239. assert.False(t, v)
  240. assert.EqualError(t, err, "certificate is in the block list")
  241. caPool.ResetCertBlocklist()
  242. v, err = c.Verify(time.Now(), caPool)
  243. assert.True(t, v)
  244. assert.Nil(t, err)
  245. v, err = c.Verify(time.Now().Add(time.Hour*1000), caPool)
  246. assert.False(t, v)
  247. assert.EqualError(t, err, "root certificate is expired")
  248. c, _, _, err = newTestCert(ca, caKey, time.Time{}, time.Time{}, []*net.IPNet{}, []*net.IPNet{}, []string{})
  249. assert.Nil(t, err)
  250. v, err = c.Verify(time.Now().Add(time.Minute*6), caPool)
  251. assert.False(t, v)
  252. assert.EqualError(t, err, "certificate is expired")
  253. // Test group assertion
  254. ca, _, caKey, err = newTestCaCertP256(time.Now(), time.Now().Add(10*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{"test1", "test2"})
  255. assert.Nil(t, err)
  256. caPem, err := ca.MarshalToPEM()
  257. assert.Nil(t, err)
  258. caPool = NewCAPool()
  259. caPool.AddCACertificate(caPem)
  260. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{"test1", "bad"})
  261. assert.Nil(t, err)
  262. v, err = c.Verify(time.Now(), caPool)
  263. assert.False(t, v)
  264. assert.EqualError(t, err, "certificate contained a group not present on the signing ca: bad")
  265. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{"test1"})
  266. assert.Nil(t, err)
  267. v, err = c.Verify(time.Now(), caPool)
  268. assert.True(t, v)
  269. assert.Nil(t, err)
  270. }
  271. func TestNebulaCertificate_Verify_IPs(t *testing.T) {
  272. _, caIp1, _ := net.ParseCIDR("10.0.0.0/16")
  273. _, caIp2, _ := net.ParseCIDR("192.168.0.0/24")
  274. ca, _, caKey, err := newTestCaCert(time.Now(), time.Now().Add(10*time.Minute), []*net.IPNet{caIp1, caIp2}, []*net.IPNet{}, []string{"test"})
  275. assert.Nil(t, err)
  276. caPem, err := ca.MarshalToPEM()
  277. assert.Nil(t, err)
  278. caPool := NewCAPool()
  279. caPool.AddCACertificate(caPem)
  280. // ip is outside the network
  281. cIp1 := &net.IPNet{IP: net.ParseIP("10.1.0.0"), Mask: []byte{255, 255, 255, 0}}
  282. cIp2 := &net.IPNet{IP: net.ParseIP("192.168.0.1"), Mask: []byte{255, 255, 0, 0}}
  283. c, _, _, err := newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{cIp1, cIp2}, []*net.IPNet{}, []string{"test"})
  284. assert.Nil(t, err)
  285. v, err := c.Verify(time.Now(), caPool)
  286. assert.False(t, v)
  287. assert.EqualError(t, err, "certificate contained an ip assignment outside the limitations of the signing ca: 10.1.0.0/24")
  288. // ip is outside the network reversed order of above
  289. cIp1 = &net.IPNet{IP: net.ParseIP("192.168.0.1"), Mask: []byte{255, 255, 255, 0}}
  290. cIp2 = &net.IPNet{IP: net.ParseIP("10.1.0.0"), Mask: []byte{255, 255, 255, 0}}
  291. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{cIp1, cIp2}, []*net.IPNet{}, []string{"test"})
  292. assert.Nil(t, err)
  293. v, err = c.Verify(time.Now(), caPool)
  294. assert.False(t, v)
  295. assert.EqualError(t, err, "certificate contained an ip assignment outside the limitations of the signing ca: 10.1.0.0/24")
  296. // ip is within the network but mask is outside
  297. cIp1 = &net.IPNet{IP: net.ParseIP("10.0.1.0"), Mask: []byte{255, 254, 0, 0}}
  298. cIp2 = &net.IPNet{IP: net.ParseIP("192.168.0.1"), Mask: []byte{255, 255, 255, 0}}
  299. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{cIp1, cIp2}, []*net.IPNet{}, []string{"test"})
  300. assert.Nil(t, err)
  301. v, err = c.Verify(time.Now(), caPool)
  302. assert.False(t, v)
  303. assert.EqualError(t, err, "certificate contained an ip assignment outside the limitations of the signing ca: 10.0.1.0/15")
  304. // ip is within the network but mask is outside reversed order of above
  305. cIp1 = &net.IPNet{IP: net.ParseIP("192.168.0.1"), Mask: []byte{255, 255, 255, 0}}
  306. cIp2 = &net.IPNet{IP: net.ParseIP("10.0.1.0"), Mask: []byte{255, 254, 0, 0}}
  307. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{cIp1, cIp2}, []*net.IPNet{}, []string{"test"})
  308. assert.Nil(t, err)
  309. v, err = c.Verify(time.Now(), caPool)
  310. assert.False(t, v)
  311. assert.EqualError(t, err, "certificate contained an ip assignment outside the limitations of the signing ca: 10.0.1.0/15")
  312. // ip and mask are within the network
  313. cIp1 = &net.IPNet{IP: net.ParseIP("10.0.1.0"), Mask: []byte{255, 255, 0, 0}}
  314. cIp2 = &net.IPNet{IP: net.ParseIP("192.168.0.1"), Mask: []byte{255, 255, 255, 128}}
  315. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{cIp1, cIp2}, []*net.IPNet{}, []string{"test"})
  316. assert.Nil(t, err)
  317. v, err = c.Verify(time.Now(), caPool)
  318. assert.True(t, v)
  319. assert.Nil(t, err)
  320. // Exact matches
  321. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{caIp1, caIp2}, []*net.IPNet{}, []string{"test"})
  322. assert.Nil(t, err)
  323. v, err = c.Verify(time.Now(), caPool)
  324. assert.True(t, v)
  325. assert.Nil(t, err)
  326. // Exact matches reversed
  327. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{caIp2, caIp1}, []*net.IPNet{}, []string{"test"})
  328. assert.Nil(t, err)
  329. v, err = c.Verify(time.Now(), caPool)
  330. assert.True(t, v)
  331. assert.Nil(t, err)
  332. // Exact matches reversed with just 1
  333. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{caIp1}, []*net.IPNet{}, []string{"test"})
  334. assert.Nil(t, err)
  335. v, err = c.Verify(time.Now(), caPool)
  336. assert.True(t, v)
  337. assert.Nil(t, err)
  338. }
  339. func TestNebulaCertificate_Verify_Subnets(t *testing.T) {
  340. _, caIp1, _ := net.ParseCIDR("10.0.0.0/16")
  341. _, caIp2, _ := net.ParseCIDR("192.168.0.0/24")
  342. ca, _, caKey, err := newTestCaCert(time.Now(), time.Now().Add(10*time.Minute), []*net.IPNet{}, []*net.IPNet{caIp1, caIp2}, []string{"test"})
  343. assert.Nil(t, err)
  344. caPem, err := ca.MarshalToPEM()
  345. assert.Nil(t, err)
  346. caPool := NewCAPool()
  347. caPool.AddCACertificate(caPem)
  348. // ip is outside the network
  349. cIp1 := &net.IPNet{IP: net.ParseIP("10.1.0.0"), Mask: []byte{255, 255, 255, 0}}
  350. cIp2 := &net.IPNet{IP: net.ParseIP("192.168.0.1"), Mask: []byte{255, 255, 0, 0}}
  351. c, _, _, err := newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{cIp1, cIp2}, []string{"test"})
  352. assert.Nil(t, err)
  353. v, err := c.Verify(time.Now(), caPool)
  354. assert.False(t, v)
  355. assert.EqualError(t, err, "certificate contained a subnet assignment outside the limitations of the signing ca: 10.1.0.0/24")
  356. // ip is outside the network reversed order of above
  357. cIp1 = &net.IPNet{IP: net.ParseIP("192.168.0.1"), Mask: []byte{255, 255, 255, 0}}
  358. cIp2 = &net.IPNet{IP: net.ParseIP("10.1.0.0"), Mask: []byte{255, 255, 255, 0}}
  359. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{cIp1, cIp2}, []string{"test"})
  360. assert.Nil(t, err)
  361. v, err = c.Verify(time.Now(), caPool)
  362. assert.False(t, v)
  363. assert.EqualError(t, err, "certificate contained a subnet assignment outside the limitations of the signing ca: 10.1.0.0/24")
  364. // ip is within the network but mask is outside
  365. cIp1 = &net.IPNet{IP: net.ParseIP("10.0.1.0"), Mask: []byte{255, 254, 0, 0}}
  366. cIp2 = &net.IPNet{IP: net.ParseIP("192.168.0.1"), Mask: []byte{255, 255, 255, 0}}
  367. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{cIp1, cIp2}, []string{"test"})
  368. assert.Nil(t, err)
  369. v, err = c.Verify(time.Now(), caPool)
  370. assert.False(t, v)
  371. assert.EqualError(t, err, "certificate contained a subnet assignment outside the limitations of the signing ca: 10.0.1.0/15")
  372. // ip is within the network but mask is outside reversed order of above
  373. cIp1 = &net.IPNet{IP: net.ParseIP("192.168.0.1"), Mask: []byte{255, 255, 255, 0}}
  374. cIp2 = &net.IPNet{IP: net.ParseIP("10.0.1.0"), Mask: []byte{255, 254, 0, 0}}
  375. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{cIp1, cIp2}, []string{"test"})
  376. assert.Nil(t, err)
  377. v, err = c.Verify(time.Now(), caPool)
  378. assert.False(t, v)
  379. assert.EqualError(t, err, "certificate contained a subnet assignment outside the limitations of the signing ca: 10.0.1.0/15")
  380. // ip and mask are within the network
  381. cIp1 = &net.IPNet{IP: net.ParseIP("10.0.1.0"), Mask: []byte{255, 255, 0, 0}}
  382. cIp2 = &net.IPNet{IP: net.ParseIP("192.168.0.1"), Mask: []byte{255, 255, 255, 128}}
  383. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{cIp1, cIp2}, []string{"test"})
  384. assert.Nil(t, err)
  385. v, err = c.Verify(time.Now(), caPool)
  386. assert.True(t, v)
  387. assert.Nil(t, err)
  388. // Exact matches
  389. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{caIp1, caIp2}, []string{"test"})
  390. assert.Nil(t, err)
  391. v, err = c.Verify(time.Now(), caPool)
  392. assert.True(t, v)
  393. assert.Nil(t, err)
  394. // Exact matches reversed
  395. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{caIp2, caIp1}, []string{"test"})
  396. assert.Nil(t, err)
  397. v, err = c.Verify(time.Now(), caPool)
  398. assert.True(t, v)
  399. assert.Nil(t, err)
  400. // Exact matches reversed with just 1
  401. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{caIp1}, []string{"test"})
  402. assert.Nil(t, err)
  403. v, err = c.Verify(time.Now(), caPool)
  404. assert.True(t, v)
  405. assert.Nil(t, err)
  406. }
  407. func TestNebulaCertificate_VerifyPrivateKey(t *testing.T) {
  408. ca, _, caKey, err := newTestCaCert(time.Time{}, time.Time{}, []*net.IPNet{}, []*net.IPNet{}, []string{})
  409. assert.Nil(t, err)
  410. err = ca.VerifyPrivateKey(Curve_CURVE25519, caKey)
  411. assert.Nil(t, err)
  412. _, _, caKey2, err := newTestCaCert(time.Time{}, time.Time{}, []*net.IPNet{}, []*net.IPNet{}, []string{})
  413. assert.Nil(t, err)
  414. err = ca.VerifyPrivateKey(Curve_CURVE25519, caKey2)
  415. assert.NotNil(t, err)
  416. c, _, priv, err := newTestCert(ca, caKey, time.Time{}, time.Time{}, []*net.IPNet{}, []*net.IPNet{}, []string{})
  417. err = c.VerifyPrivateKey(Curve_CURVE25519, priv)
  418. assert.Nil(t, err)
  419. _, priv2 := x25519Keypair()
  420. err = c.VerifyPrivateKey(Curve_CURVE25519, priv2)
  421. assert.NotNil(t, err)
  422. }
  423. func TestNebulaCertificate_VerifyPrivateKeyP256(t *testing.T) {
  424. ca, _, caKey, err := newTestCaCertP256(time.Time{}, time.Time{}, []*net.IPNet{}, []*net.IPNet{}, []string{})
  425. assert.Nil(t, err)
  426. err = ca.VerifyPrivateKey(Curve_P256, caKey)
  427. assert.Nil(t, err)
  428. _, _, caKey2, err := newTestCaCertP256(time.Time{}, time.Time{}, []*net.IPNet{}, []*net.IPNet{}, []string{})
  429. assert.Nil(t, err)
  430. err = ca.VerifyPrivateKey(Curve_P256, caKey2)
  431. assert.NotNil(t, err)
  432. c, _, priv, err := newTestCert(ca, caKey, time.Time{}, time.Time{}, []*net.IPNet{}, []*net.IPNet{}, []string{})
  433. err = c.VerifyPrivateKey(Curve_P256, priv)
  434. assert.Nil(t, err)
  435. _, priv2 := p256Keypair()
  436. err = c.VerifyPrivateKey(Curve_P256, priv2)
  437. assert.NotNil(t, err)
  438. }
  439. func TestNewCAPoolFromBytes(t *testing.T) {
  440. noNewLines := `
  441. # Current provisional, Remove once everything moves over to the real root.
  442. -----BEGIN NEBULA CERTIFICATE-----
  443. CkAKDm5lYnVsYSByb290IGNhKJfap9AFMJfg1+YGOiCUQGByMuNRhIlQBOyzXWbL
  444. vcKBwDhov900phEfJ5DN3kABEkDCq5R8qBiu8sl54yVfgRcQXEDt3cHr8UTSLszv
  445. bzBEr00kERQxxTzTsH8cpYEgRoipvmExvg8WP8NdAJEYJosB
  446. -----END NEBULA CERTIFICATE-----
  447. # root-ca01
  448. -----BEGIN NEBULA CERTIFICATE-----
  449. CkMKEW5lYnVsYSByb290IGNhIDAxKJL2u9EFMJL86+cGOiDPXMH4oU6HZTk/CqTG
  450. BVG+oJpAoqokUBbI4U0N8CSfpUABEkB/Pm5A2xyH/nc8mg/wvGUWG3pZ7nHzaDMf
  451. 8/phAUt+FLzqTECzQKisYswKvE3pl9mbEYKbOdIHrxdIp95mo4sF
  452. -----END NEBULA CERTIFICATE-----
  453. `
  454. withNewLines := `
  455. # Current provisional, Remove once everything moves over to the real root.
  456. -----BEGIN NEBULA CERTIFICATE-----
  457. CkAKDm5lYnVsYSByb290IGNhKJfap9AFMJfg1+YGOiCUQGByMuNRhIlQBOyzXWbL
  458. vcKBwDhov900phEfJ5DN3kABEkDCq5R8qBiu8sl54yVfgRcQXEDt3cHr8UTSLszv
  459. bzBEr00kERQxxTzTsH8cpYEgRoipvmExvg8WP8NdAJEYJosB
  460. -----END NEBULA CERTIFICATE-----
  461. # root-ca01
  462. -----BEGIN NEBULA CERTIFICATE-----
  463. CkMKEW5lYnVsYSByb290IGNhIDAxKJL2u9EFMJL86+cGOiDPXMH4oU6HZTk/CqTG
  464. BVG+oJpAoqokUBbI4U0N8CSfpUABEkB/Pm5A2xyH/nc8mg/wvGUWG3pZ7nHzaDMf
  465. 8/phAUt+FLzqTECzQKisYswKvE3pl9mbEYKbOdIHrxdIp95mo4sF
  466. -----END NEBULA CERTIFICATE-----
  467. `
  468. expired := `
  469. # expired certificate
  470. -----BEGIN NEBULA CERTIFICATE-----
  471. CjkKB2V4cGlyZWQouPmWjQYwufmWjQY6ILCRaoCkJlqHgv5jfDN4lzLHBvDzaQm4
  472. vZxfu144hmgjQAESQG4qlnZi8DncvD/LDZnLgJHOaX1DWCHHEh59epVsC+BNgTie
  473. WH1M9n4O7cFtGlM6sJJOS+rCVVEJ3ABS7+MPdQs=
  474. -----END NEBULA CERTIFICATE-----
  475. `
  476. p256 := `
  477. # p256 certificate
  478. -----BEGIN NEBULA CERTIFICATE-----
  479. CmYKEG5lYnVsYSBQMjU2IHRlc3Qo4s+7mgYw4tXrsAc6QQRkaW2jFmllYvN4+/k2
  480. 6tctO9sPT3jOx8ES6M1nIqOhpTmZeabF/4rELDqPV4aH5jfJut798DUXql0FlF8H
  481. 76gvQAGgBgESRzBFAiEAib0/te6eMiZOKD8gdDeloMTS0wGuX2t0C7TFdUhAQzgC
  482. IBNWYMep3ysx9zCgknfG5dKtwGTaqF++BWKDYdyl34KX
  483. -----END NEBULA CERTIFICATE-----
  484. `
  485. rootCA := NebulaCertificate{
  486. Details: NebulaCertificateDetails{
  487. Name: "nebula root ca",
  488. },
  489. }
  490. rootCA01 := NebulaCertificate{
  491. Details: NebulaCertificateDetails{
  492. Name: "nebula root ca 01",
  493. },
  494. }
  495. rootCAP256 := NebulaCertificate{
  496. Details: NebulaCertificateDetails{
  497. Name: "nebula P256 test",
  498. },
  499. }
  500. p, err := NewCAPoolFromBytes([]byte(noNewLines))
  501. assert.Nil(t, err)
  502. assert.Equal(t, p.CAs[string("c9bfaf7ce8e84b2eeda2e27b469f4b9617bde192efd214b68891ecda6ed49522")].Details.Name, rootCA.Details.Name)
  503. assert.Equal(t, p.CAs[string("5c9c3f23e7ee7fe97637cbd3a0a5b854154d1d9aaaf7b566a51f4a88f76b64cd")].Details.Name, rootCA01.Details.Name)
  504. pp, err := NewCAPoolFromBytes([]byte(withNewLines))
  505. assert.Nil(t, err)
  506. assert.Equal(t, pp.CAs[string("c9bfaf7ce8e84b2eeda2e27b469f4b9617bde192efd214b68891ecda6ed49522")].Details.Name, rootCA.Details.Name)
  507. assert.Equal(t, pp.CAs[string("5c9c3f23e7ee7fe97637cbd3a0a5b854154d1d9aaaf7b566a51f4a88f76b64cd")].Details.Name, rootCA01.Details.Name)
  508. // expired cert, no valid certs
  509. ppp, err := NewCAPoolFromBytes([]byte(expired))
  510. assert.Equal(t, ErrExpired, err)
  511. assert.Equal(t, ppp.CAs[string("152070be6bb19bc9e3bde4c2f0e7d8f4ff5448b4c9856b8eccb314fade0229b0")].Details.Name, "expired")
  512. // expired cert, with valid certs
  513. pppp, err := NewCAPoolFromBytes(append([]byte(expired), noNewLines...))
  514. assert.Equal(t, ErrExpired, err)
  515. assert.Equal(t, pppp.CAs[string("c9bfaf7ce8e84b2eeda2e27b469f4b9617bde192efd214b68891ecda6ed49522")].Details.Name, rootCA.Details.Name)
  516. assert.Equal(t, pppp.CAs[string("5c9c3f23e7ee7fe97637cbd3a0a5b854154d1d9aaaf7b566a51f4a88f76b64cd")].Details.Name, rootCA01.Details.Name)
  517. assert.Equal(t, pppp.CAs[string("152070be6bb19bc9e3bde4c2f0e7d8f4ff5448b4c9856b8eccb314fade0229b0")].Details.Name, "expired")
  518. assert.Equal(t, len(pppp.CAs), 3)
  519. ppppp, err := NewCAPoolFromBytes([]byte(p256))
  520. assert.Nil(t, err)
  521. assert.Equal(t, ppppp.CAs[string("a7938893ec8c4ef769b06d7f425e5e46f7a7f5ffa49c3bcf4a86b608caba9159")].Details.Name, rootCAP256.Details.Name)
  522. assert.Equal(t, len(ppppp.CAs), 1)
  523. }
  524. func appendByteSlices(b ...[]byte) []byte {
  525. retSlice := []byte{}
  526. for _, v := range b {
  527. retSlice = append(retSlice, v...)
  528. }
  529. return retSlice
  530. }
  531. func TestUnmrshalCertPEM(t *testing.T) {
  532. goodCert := []byte(`
  533. # A good cert
  534. -----BEGIN NEBULA CERTIFICATE-----
  535. CkAKDm5lYnVsYSByb290IGNhKJfap9AFMJfg1+YGOiCUQGByMuNRhIlQBOyzXWbL
  536. vcKBwDhov900phEfJ5DN3kABEkDCq5R8qBiu8sl54yVfgRcQXEDt3cHr8UTSLszv
  537. bzBEr00kERQxxTzTsH8cpYEgRoipvmExvg8WP8NdAJEYJosB
  538. -----END NEBULA CERTIFICATE-----
  539. `)
  540. badBanner := []byte(`# A bad banner
  541. -----BEGIN NOT A NEBULA CERTIFICATE-----
  542. CkAKDm5lYnVsYSByb290IGNhKJfap9AFMJfg1+YGOiCUQGByMuNRhIlQBOyzXWbL
  543. vcKBwDhov900phEfJ5DN3kABEkDCq5R8qBiu8sl54yVfgRcQXEDt3cHr8UTSLszv
  544. bzBEr00kERQxxTzTsH8cpYEgRoipvmExvg8WP8NdAJEYJosB
  545. -----END NOT A NEBULA CERTIFICATE-----
  546. `)
  547. invalidPem := []byte(`# Not a valid PEM format
  548. -BEGIN NEBULA CERTIFICATE-----
  549. CkAKDm5lYnVsYSByb290IGNhKJfap9AFMJfg1+YGOiCUQGByMuNRhIlQBOyzXWbL
  550. vcKBwDhov900phEfJ5DN3kABEkDCq5R8qBiu8sl54yVfgRcQXEDt3cHr8UTSLszv
  551. bzBEr00kERQxxTzTsH8cpYEgRoipvmExvg8WP8NdAJEYJosB
  552. -END NEBULA CERTIFICATE----`)
  553. certBundle := appendByteSlices(goodCert, badBanner, invalidPem)
  554. // Success test case
  555. cert, rest, err := UnmarshalNebulaCertificateFromPEM(certBundle)
  556. assert.NotNil(t, cert)
  557. assert.Equal(t, rest, append(badBanner, invalidPem...))
  558. assert.Nil(t, err)
  559. // Fail due to invalid banner.
  560. cert, rest, err = UnmarshalNebulaCertificateFromPEM(rest)
  561. assert.Nil(t, cert)
  562. assert.Equal(t, rest, invalidPem)
  563. assert.EqualError(t, err, "bytes did not contain a proper nebula certificate banner")
  564. // Fail due to ivalid PEM format, because
  565. // it's missing the requisite pre-encapsulation boundary.
  566. cert, rest, err = UnmarshalNebulaCertificateFromPEM(rest)
  567. assert.Nil(t, cert)
  568. assert.Equal(t, rest, invalidPem)
  569. assert.EqualError(t, err, "input did not contain a valid PEM encoded block")
  570. }
  571. func TestUnmarshalSigningPrivateKey(t *testing.T) {
  572. privKey := []byte(`# A good key
  573. -----BEGIN NEBULA ED25519 PRIVATE KEY-----
  574. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
  575. -----END NEBULA ED25519 PRIVATE KEY-----
  576. `)
  577. privP256Key := []byte(`# A good key
  578. -----BEGIN NEBULA ECDSA P256 PRIVATE KEY-----
  579. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
  580. -----END NEBULA ECDSA P256 PRIVATE KEY-----
  581. `)
  582. shortKey := []byte(`# A short key
  583. -----BEGIN NEBULA ED25519 PRIVATE KEY-----
  584. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  585. -----END NEBULA ED25519 PRIVATE KEY-----
  586. `)
  587. invalidBanner := []byte(`# Invalid banner
  588. -----BEGIN NOT A NEBULA PRIVATE KEY-----
  589. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
  590. -----END NOT A NEBULA PRIVATE KEY-----
  591. `)
  592. invalidPem := []byte(`# Not a valid PEM format
  593. -BEGIN NEBULA ED25519 PRIVATE KEY-----
  594. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
  595. -END NEBULA ED25519 PRIVATE KEY-----`)
  596. keyBundle := appendByteSlices(privKey, privP256Key, shortKey, invalidBanner, invalidPem)
  597. // Success test case
  598. k, rest, curve, err := UnmarshalSigningPrivateKey(keyBundle)
  599. assert.Len(t, k, 64)
  600. assert.Equal(t, rest, appendByteSlices(privP256Key, shortKey, invalidBanner, invalidPem))
  601. assert.Equal(t, Curve_CURVE25519, curve)
  602. assert.Nil(t, err)
  603. // Success test case
  604. k, rest, curve, err = UnmarshalSigningPrivateKey(rest)
  605. assert.Len(t, k, 32)
  606. assert.Equal(t, rest, appendByteSlices(shortKey, invalidBanner, invalidPem))
  607. assert.Equal(t, Curve_P256, curve)
  608. assert.Nil(t, err)
  609. // Fail due to short key
  610. k, rest, curve, err = UnmarshalSigningPrivateKey(rest)
  611. assert.Nil(t, k)
  612. assert.Equal(t, rest, appendByteSlices(invalidBanner, invalidPem))
  613. assert.EqualError(t, err, "key was not 64 bytes, is invalid Ed25519 private key")
  614. // Fail due to invalid banner
  615. k, rest, curve, err = UnmarshalSigningPrivateKey(rest)
  616. assert.Nil(t, k)
  617. assert.Equal(t, rest, invalidPem)
  618. assert.EqualError(t, err, "bytes did not contain a proper nebula Ed25519/ECDSA private key banner")
  619. // Fail due to ivalid PEM format, because
  620. // it's missing the requisite pre-encapsulation boundary.
  621. k, rest, curve, err = UnmarshalSigningPrivateKey(rest)
  622. assert.Nil(t, k)
  623. assert.Equal(t, rest, invalidPem)
  624. assert.EqualError(t, err, "input did not contain a valid PEM encoded block")
  625. }
  626. func TestDecryptAndUnmarshalSigningPrivateKey(t *testing.T) {
  627. passphrase := []byte("DO NOT USE THIS KEY")
  628. privKey := []byte(`# A good key
  629. -----BEGIN NEBULA ED25519 ENCRYPTED PRIVATE KEY-----
  630. CjwKC0FFUy0yNTYtR0NNEi0IExCAgIABGAEgBCognnjujd67Vsv99p22wfAjQaDT
  631. oCMW1mdjkU3gACKNW4MSXOWR9Sts4C81yk1RUku2gvGKs3TB9LYoklLsIizSYOLl
  632. +Vs//O1T0I1Xbml2XBAROsb/VSoDln/6LMqR4B6fn6B3GOsLBBqRI8daDl9lRMPB
  633. qrlJ69wer3ZUHFXA
  634. -----END NEBULA ED25519 ENCRYPTED PRIVATE KEY-----
  635. `)
  636. shortKey := []byte(`# A key which, once decrypted, is too short
  637. -----BEGIN NEBULA ED25519 ENCRYPTED PRIVATE KEY-----
  638. CjwKC0FFUy0yNTYtR0NNEi0IExCAgIABGAEgBCoga5h8owMEBWRSMMJKzuUvWce7
  639. k0qlBkQmCxiuLh80MuASW70YcKt8jeEIS2axo2V6zAKA9TSMcCsJW1kDDXEtL/xe
  640. GLF5T7sDl5COp4LU3pGxpV+KoeQ/S3gQCAAcnaOtnJQX+aSDnbO3jCHyP7U9CHbs
  641. rQr3bdH3Oy/WiYU=
  642. -----END NEBULA ED25519 ENCRYPTED PRIVATE KEY-----
  643. `)
  644. invalidBanner := []byte(`# Invalid banner (not encrypted)
  645. -----BEGIN NEBULA ED25519 PRIVATE KEY-----
  646. bWRp2CTVFhW9HD/qCd28ltDgK3w8VXSeaEYczDWos8sMUBqDb9jP3+NYwcS4lURG
  647. XgLvodMXZJuaFPssp+WwtA==
  648. -----END NEBULA ED25519 PRIVATE KEY-----
  649. `)
  650. invalidPem := []byte(`# Not a valid PEM format
  651. -BEGIN NEBULA ED25519 ENCRYPTED PRIVATE KEY-----
  652. CjwKC0FFUy0yNTYtR0NNEi0IExCAgIABGAEgBCognnjujd67Vsv99p22wfAjQaDT
  653. oCMW1mdjkU3gACKNW4MSXOWR9Sts4C81yk1RUku2gvGKs3TB9LYoklLsIizSYOLl
  654. +Vs//O1T0I1Xbml2XBAROsb/VSoDln/6LMqR4B6fn6B3GOsLBBqRI8daDl9lRMPB
  655. qrlJ69wer3ZUHFXA
  656. -END NEBULA ED25519 ENCRYPTED PRIVATE KEY-----
  657. `)
  658. keyBundle := appendByteSlices(privKey, shortKey, invalidBanner, invalidPem)
  659. // Success test case
  660. curve, k, rest, err := DecryptAndUnmarshalSigningPrivateKey(passphrase, keyBundle)
  661. assert.Nil(t, err)
  662. assert.Equal(t, Curve_CURVE25519, curve)
  663. assert.Len(t, k, 64)
  664. assert.Equal(t, rest, appendByteSlices(shortKey, invalidBanner, invalidPem))
  665. // Fail due to short key
  666. curve, k, rest, err = DecryptAndUnmarshalSigningPrivateKey(passphrase, rest)
  667. assert.EqualError(t, err, "key was not 64 bytes, is invalid ed25519 private key")
  668. assert.Nil(t, k)
  669. assert.Equal(t, rest, appendByteSlices(invalidBanner, invalidPem))
  670. // Fail due to invalid banner
  671. curve, k, rest, err = DecryptAndUnmarshalSigningPrivateKey(passphrase, rest)
  672. assert.EqualError(t, err, "bytes did not contain a proper nebula encrypted Ed25519/ECDSA private key banner")
  673. assert.Nil(t, k)
  674. assert.Equal(t, rest, invalidPem)
  675. // Fail due to ivalid PEM format, because
  676. // it's missing the requisite pre-encapsulation boundary.
  677. curve, k, rest, err = DecryptAndUnmarshalSigningPrivateKey(passphrase, rest)
  678. assert.EqualError(t, err, "input did not contain a valid PEM encoded block")
  679. assert.Nil(t, k)
  680. assert.Equal(t, rest, invalidPem)
  681. // Fail due to invalid passphrase
  682. curve, k, rest, err = DecryptAndUnmarshalSigningPrivateKey([]byte("invalid passphrase"), privKey)
  683. assert.EqualError(t, err, "invalid passphrase or corrupt private key")
  684. assert.Nil(t, k)
  685. assert.Equal(t, rest, []byte{})
  686. }
  687. func TestEncryptAndMarshalSigningPrivateKey(t *testing.T) {
  688. // Having proved that decryption works correctly above, we can test the
  689. // encryption function produces a value which can be decrypted
  690. passphrase := []byte("passphrase")
  691. bytes := []byte("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")
  692. kdfParams := NewArgon2Parameters(64*1024, 4, 3)
  693. key, err := EncryptAndMarshalSigningPrivateKey(Curve_CURVE25519, bytes, passphrase, kdfParams)
  694. assert.Nil(t, err)
  695. // Verify the "key" can be decrypted successfully
  696. curve, k, rest, err := DecryptAndUnmarshalSigningPrivateKey(passphrase, key)
  697. assert.Len(t, k, 64)
  698. assert.Equal(t, Curve_CURVE25519, curve)
  699. assert.Equal(t, rest, []byte{})
  700. assert.Nil(t, err)
  701. // EncryptAndMarshalEd25519PrivateKey does not create any errors itself
  702. }
  703. func TestUnmarshalPrivateKey(t *testing.T) {
  704. privKey := []byte(`# A good key
  705. -----BEGIN NEBULA X25519 PRIVATE KEY-----
  706. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
  707. -----END NEBULA X25519 PRIVATE KEY-----
  708. `)
  709. privP256Key := []byte(`# A good key
  710. -----BEGIN NEBULA P256 PRIVATE KEY-----
  711. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
  712. -----END NEBULA P256 PRIVATE KEY-----
  713. `)
  714. shortKey := []byte(`# A short key
  715. -----BEGIN NEBULA X25519 PRIVATE KEY-----
  716. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
  717. -----END NEBULA X25519 PRIVATE KEY-----
  718. `)
  719. invalidBanner := []byte(`# Invalid banner
  720. -----BEGIN NOT A NEBULA PRIVATE KEY-----
  721. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
  722. -----END NOT A NEBULA PRIVATE KEY-----
  723. `)
  724. invalidPem := []byte(`# Not a valid PEM format
  725. -BEGIN NEBULA X25519 PRIVATE KEY-----
  726. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
  727. -END NEBULA X25519 PRIVATE KEY-----`)
  728. keyBundle := appendByteSlices(privKey, privP256Key, shortKey, invalidBanner, invalidPem)
  729. // Success test case
  730. k, rest, curve, err := UnmarshalPrivateKey(keyBundle)
  731. assert.Len(t, k, 32)
  732. assert.Equal(t, rest, appendByteSlices(privP256Key, shortKey, invalidBanner, invalidPem))
  733. assert.Equal(t, Curve_CURVE25519, curve)
  734. assert.Nil(t, err)
  735. // Success test case
  736. k, rest, curve, err = UnmarshalPrivateKey(rest)
  737. assert.Len(t, k, 32)
  738. assert.Equal(t, rest, appendByteSlices(shortKey, invalidBanner, invalidPem))
  739. assert.Equal(t, Curve_P256, curve)
  740. assert.Nil(t, err)
  741. // Fail due to short key
  742. k, rest, curve, err = UnmarshalPrivateKey(rest)
  743. assert.Nil(t, k)
  744. assert.Equal(t, rest, appendByteSlices(invalidBanner, invalidPem))
  745. assert.EqualError(t, err, "key was not 32 bytes, is invalid CURVE25519 private key")
  746. // Fail due to invalid banner
  747. k, rest, curve, err = UnmarshalPrivateKey(rest)
  748. assert.Nil(t, k)
  749. assert.Equal(t, rest, invalidPem)
  750. assert.EqualError(t, err, "bytes did not contain a proper nebula private key banner")
  751. // Fail due to ivalid PEM format, because
  752. // it's missing the requisite pre-encapsulation boundary.
  753. k, rest, curve, err = UnmarshalPrivateKey(rest)
  754. assert.Nil(t, k)
  755. assert.Equal(t, rest, invalidPem)
  756. assert.EqualError(t, err, "input did not contain a valid PEM encoded block")
  757. }
  758. func TestUnmarshalEd25519PublicKey(t *testing.T) {
  759. pubKey := []byte(`# A good key
  760. -----BEGIN NEBULA ED25519 PUBLIC KEY-----
  761. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
  762. -----END NEBULA ED25519 PUBLIC KEY-----
  763. `)
  764. shortKey := []byte(`# A short key
  765. -----BEGIN NEBULA ED25519 PUBLIC KEY-----
  766. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
  767. -----END NEBULA ED25519 PUBLIC KEY-----
  768. `)
  769. invalidBanner := []byte(`# Invalid banner
  770. -----BEGIN NOT A NEBULA PUBLIC KEY-----
  771. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
  772. -----END NOT A NEBULA PUBLIC KEY-----
  773. `)
  774. invalidPem := []byte(`# Not a valid PEM format
  775. -BEGIN NEBULA ED25519 PUBLIC KEY-----
  776. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
  777. -END NEBULA ED25519 PUBLIC KEY-----`)
  778. keyBundle := appendByteSlices(pubKey, shortKey, invalidBanner, invalidPem)
  779. // Success test case
  780. k, rest, err := UnmarshalEd25519PublicKey(keyBundle)
  781. assert.Equal(t, len(k), 32)
  782. assert.Nil(t, err)
  783. assert.Equal(t, rest, appendByteSlices(shortKey, invalidBanner, invalidPem))
  784. // Fail due to short key
  785. k, rest, err = UnmarshalEd25519PublicKey(rest)
  786. assert.Nil(t, k)
  787. assert.Equal(t, rest, appendByteSlices(invalidBanner, invalidPem))
  788. assert.EqualError(t, err, "key was not 32 bytes, is invalid ed25519 public key")
  789. // Fail due to invalid banner
  790. k, rest, err = UnmarshalEd25519PublicKey(rest)
  791. assert.Nil(t, k)
  792. assert.EqualError(t, err, "bytes did not contain a proper nebula Ed25519 public key banner")
  793. assert.Equal(t, rest, invalidPem)
  794. // Fail due to ivalid PEM format, because
  795. // it's missing the requisite pre-encapsulation boundary.
  796. k, rest, err = UnmarshalEd25519PublicKey(rest)
  797. assert.Nil(t, k)
  798. assert.Equal(t, rest, invalidPem)
  799. assert.EqualError(t, err, "input did not contain a valid PEM encoded block")
  800. }
  801. func TestUnmarshalX25519PublicKey(t *testing.T) {
  802. pubKey := []byte(`# A good key
  803. -----BEGIN NEBULA X25519 PUBLIC KEY-----
  804. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
  805. -----END NEBULA X25519 PUBLIC KEY-----
  806. `)
  807. pubP256Key := []byte(`# A good key
  808. -----BEGIN NEBULA P256 PUBLIC KEY-----
  809. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  810. AAAAAAAAAAAAAAAAAAAAAAA=
  811. -----END NEBULA P256 PUBLIC KEY-----
  812. `)
  813. shortKey := []byte(`# A short key
  814. -----BEGIN NEBULA X25519 PUBLIC KEY-----
  815. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
  816. -----END NEBULA X25519 PUBLIC KEY-----
  817. `)
  818. invalidBanner := []byte(`# Invalid banner
  819. -----BEGIN NOT A NEBULA PUBLIC KEY-----
  820. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
  821. -----END NOT A NEBULA PUBLIC KEY-----
  822. `)
  823. invalidPem := []byte(`# Not a valid PEM format
  824. -BEGIN NEBULA X25519 PUBLIC KEY-----
  825. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
  826. -END NEBULA X25519 PUBLIC KEY-----`)
  827. keyBundle := appendByteSlices(pubKey, pubP256Key, shortKey, invalidBanner, invalidPem)
  828. // Success test case
  829. k, rest, curve, err := UnmarshalPublicKey(keyBundle)
  830. assert.Equal(t, len(k), 32)
  831. assert.Nil(t, err)
  832. assert.Equal(t, rest, appendByteSlices(pubP256Key, shortKey, invalidBanner, invalidPem))
  833. assert.Equal(t, Curve_CURVE25519, curve)
  834. // Success test case
  835. k, rest, curve, err = UnmarshalPublicKey(rest)
  836. assert.Equal(t, len(k), 65)
  837. assert.Nil(t, err)
  838. assert.Equal(t, rest, appendByteSlices(shortKey, invalidBanner, invalidPem))
  839. assert.Equal(t, Curve_P256, curve)
  840. // Fail due to short key
  841. k, rest, curve, err = UnmarshalPublicKey(rest)
  842. assert.Nil(t, k)
  843. assert.Equal(t, rest, appendByteSlices(invalidBanner, invalidPem))
  844. assert.EqualError(t, err, "key was not 32 bytes, is invalid CURVE25519 public key")
  845. // Fail due to invalid banner
  846. k, rest, curve, err = UnmarshalPublicKey(rest)
  847. assert.Nil(t, k)
  848. assert.EqualError(t, err, "bytes did not contain a proper nebula public key banner")
  849. assert.Equal(t, rest, invalidPem)
  850. // Fail due to ivalid PEM format, because
  851. // it's missing the requisite pre-encapsulation boundary.
  852. k, rest, curve, err = UnmarshalPublicKey(rest)
  853. assert.Nil(t, k)
  854. assert.Equal(t, rest, invalidPem)
  855. assert.EqualError(t, err, "input did not contain a valid PEM encoded block")
  856. }
  857. // Ensure that upgrading the protobuf library does not change how certificates
  858. // are marshalled, since this would break signature verification
  859. func TestMarshalingNebulaCertificateConsistency(t *testing.T) {
  860. before := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
  861. after := time.Date(2017, time.January, 18, 28, 40, 0, 0, time.UTC)
  862. pubKey := []byte("1234567890abcedfghij1234567890ab")
  863. nc := NebulaCertificate{
  864. Details: NebulaCertificateDetails{
  865. Name: "testing",
  866. Ips: []*net.IPNet{
  867. {IP: net.ParseIP("10.1.1.1"), Mask: net.IPMask(net.ParseIP("255.255.255.0"))},
  868. {IP: net.ParseIP("10.1.1.2"), Mask: net.IPMask(net.ParseIP("255.255.0.0"))},
  869. {IP: net.ParseIP("10.1.1.3"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
  870. },
  871. Subnets: []*net.IPNet{
  872. {IP: net.ParseIP("9.1.1.1"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
  873. {IP: net.ParseIP("9.1.1.2"), Mask: net.IPMask(net.ParseIP("255.255.255.0"))},
  874. {IP: net.ParseIP("9.1.1.3"), Mask: net.IPMask(net.ParseIP("255.255.0.0"))},
  875. },
  876. Groups: []string{"test-group1", "test-group2", "test-group3"},
  877. NotBefore: before,
  878. NotAfter: after,
  879. PublicKey: pubKey,
  880. IsCA: false,
  881. Issuer: "1234567890abcedfghij1234567890ab",
  882. },
  883. Signature: []byte("1234567890abcedfghij1234567890ab"),
  884. }
  885. b, err := nc.Marshal()
  886. assert.Nil(t, err)
  887. //t.Log("Cert size:", len(b))
  888. assert.Equal(t, "0aa2010a0774657374696e67121b8182845080feffff0f828284508080fcff0f8382845080fe83f80f1a1b8182844880fe83f80f8282844880feffff0f838284488080fcff0f220b746573742d67726f757031220b746573742d67726f757032220b746573742d67726f75703328f0e0e7d70430a08681c4053a20313233343536373839306162636564666768696a3132333435363738393061624a081234567890abcedf1220313233343536373839306162636564666768696a313233343536373839306162", fmt.Sprintf("%x", b))
  889. b, err = proto.Marshal(nc.getRawDetails())
  890. assert.Nil(t, err)
  891. //t.Log("Raw cert size:", len(b))
  892. assert.Equal(t, "0a0774657374696e67121b8182845080feffff0f828284508080fcff0f8382845080fe83f80f1a1b8182844880fe83f80f8282844880feffff0f838284488080fcff0f220b746573742d67726f757031220b746573742d67726f757032220b746573742d67726f75703328f0e0e7d70430a08681c4053a20313233343536373839306162636564666768696a3132333435363738393061624a081234567890abcedf", fmt.Sprintf("%x", b))
  893. }
  894. func TestNebulaCertificate_Copy(t *testing.T) {
  895. ca, _, caKey, err := newTestCaCert(time.Now(), time.Now().Add(10*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{})
  896. assert.Nil(t, err)
  897. c, _, _, err := newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{})
  898. assert.Nil(t, err)
  899. cc := c.Copy()
  900. test.AssertDeepCopyEqual(t, c, cc)
  901. }
  902. func TestUnmarshalNebulaCertificate(t *testing.T) {
  903. // Test that we don't panic with an invalid certificate (#332)
  904. data := []byte("\x98\x00\x00")
  905. _, err := UnmarshalNebulaCertificate(data)
  906. assert.EqualError(t, err, "encoded Details was nil")
  907. }
  908. func newTestCaCert(before, after time.Time, ips, subnets []*net.IPNet, groups []string) (*NebulaCertificate, []byte, []byte, error) {
  909. pub, priv, err := ed25519.GenerateKey(rand.Reader)
  910. if before.IsZero() {
  911. before = time.Now().Add(time.Second * -60).Round(time.Second)
  912. }
  913. if after.IsZero() {
  914. after = time.Now().Add(time.Second * 60).Round(time.Second)
  915. }
  916. nc := &NebulaCertificate{
  917. Details: NebulaCertificateDetails{
  918. Name: "test ca",
  919. NotBefore: time.Unix(before.Unix(), 0),
  920. NotAfter: time.Unix(after.Unix(), 0),
  921. PublicKey: pub,
  922. IsCA: true,
  923. InvertedGroups: make(map[string]struct{}),
  924. },
  925. }
  926. if len(ips) > 0 {
  927. nc.Details.Ips = ips
  928. }
  929. if len(subnets) > 0 {
  930. nc.Details.Subnets = subnets
  931. }
  932. if len(groups) > 0 {
  933. nc.Details.Groups = groups
  934. }
  935. err = nc.Sign(Curve_CURVE25519, priv)
  936. if err != nil {
  937. return nil, nil, nil, err
  938. }
  939. return nc, pub, priv, nil
  940. }
  941. func newTestCaCertP256(before, after time.Time, ips, subnets []*net.IPNet, groups []string) (*NebulaCertificate, []byte, []byte, error) {
  942. priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  943. pub := elliptic.Marshal(elliptic.P256(), priv.PublicKey.X, priv.PublicKey.Y)
  944. rawPriv := priv.D.FillBytes(make([]byte, 32))
  945. if before.IsZero() {
  946. before = time.Now().Add(time.Second * -60).Round(time.Second)
  947. }
  948. if after.IsZero() {
  949. after = time.Now().Add(time.Second * 60).Round(time.Second)
  950. }
  951. nc := &NebulaCertificate{
  952. Details: NebulaCertificateDetails{
  953. Name: "test ca",
  954. NotBefore: time.Unix(before.Unix(), 0),
  955. NotAfter: time.Unix(after.Unix(), 0),
  956. PublicKey: pub,
  957. IsCA: true,
  958. Curve: Curve_P256,
  959. InvertedGroups: make(map[string]struct{}),
  960. },
  961. }
  962. if len(ips) > 0 {
  963. nc.Details.Ips = ips
  964. }
  965. if len(subnets) > 0 {
  966. nc.Details.Subnets = subnets
  967. }
  968. if len(groups) > 0 {
  969. nc.Details.Groups = groups
  970. }
  971. err = nc.Sign(Curve_P256, rawPriv)
  972. if err != nil {
  973. return nil, nil, nil, err
  974. }
  975. return nc, pub, rawPriv, nil
  976. }
  977. func newTestCert(ca *NebulaCertificate, key []byte, before, after time.Time, ips, subnets []*net.IPNet, groups []string) (*NebulaCertificate, []byte, []byte, error) {
  978. issuer, err := ca.Sha256Sum()
  979. if err != nil {
  980. return nil, nil, nil, err
  981. }
  982. if before.IsZero() {
  983. before = time.Now().Add(time.Second * -60).Round(time.Second)
  984. }
  985. if after.IsZero() {
  986. after = time.Now().Add(time.Second * 60).Round(time.Second)
  987. }
  988. if len(groups) == 0 {
  989. groups = []string{"test-group1", "test-group2", "test-group3"}
  990. }
  991. if len(ips) == 0 {
  992. ips = []*net.IPNet{
  993. {IP: net.ParseIP("10.1.1.1").To4(), Mask: net.IPMask(net.ParseIP("255.255.255.0").To4())},
  994. {IP: net.ParseIP("10.1.1.2").To4(), Mask: net.IPMask(net.ParseIP("255.255.0.0").To4())},
  995. {IP: net.ParseIP("10.1.1.3").To4(), Mask: net.IPMask(net.ParseIP("255.0.255.0").To4())},
  996. }
  997. }
  998. if len(subnets) == 0 {
  999. subnets = []*net.IPNet{
  1000. {IP: net.ParseIP("9.1.1.1").To4(), Mask: net.IPMask(net.ParseIP("255.0.255.0").To4())},
  1001. {IP: net.ParseIP("9.1.1.2").To4(), Mask: net.IPMask(net.ParseIP("255.255.255.0").To4())},
  1002. {IP: net.ParseIP("9.1.1.3").To4(), Mask: net.IPMask(net.ParseIP("255.255.0.0").To4())},
  1003. }
  1004. }
  1005. var pub, rawPriv []byte
  1006. switch ca.Details.Curve {
  1007. case Curve_CURVE25519:
  1008. pub, rawPriv = x25519Keypair()
  1009. case Curve_P256:
  1010. pub, rawPriv = p256Keypair()
  1011. default:
  1012. return nil, nil, nil, fmt.Errorf("unknown curve: %v", ca.Details.Curve)
  1013. }
  1014. nc := &NebulaCertificate{
  1015. Details: NebulaCertificateDetails{
  1016. Name: "testing",
  1017. Ips: ips,
  1018. Subnets: subnets,
  1019. Groups: groups,
  1020. NotBefore: time.Unix(before.Unix(), 0),
  1021. NotAfter: time.Unix(after.Unix(), 0),
  1022. PublicKey: pub,
  1023. IsCA: false,
  1024. Curve: ca.Details.Curve,
  1025. Issuer: issuer,
  1026. InvertedGroups: make(map[string]struct{}),
  1027. },
  1028. }
  1029. err = nc.Sign(ca.Details.Curve, key)
  1030. if err != nil {
  1031. return nil, nil, nil, err
  1032. }
  1033. return nc, pub, rawPriv, nil
  1034. }
  1035. func x25519Keypair() ([]byte, []byte) {
  1036. privkey := make([]byte, 32)
  1037. if _, err := io.ReadFull(rand.Reader, privkey); err != nil {
  1038. panic(err)
  1039. }
  1040. pubkey, err := curve25519.X25519(privkey, curve25519.Basepoint)
  1041. if err != nil {
  1042. panic(err)
  1043. }
  1044. return pubkey, privkey
  1045. }
  1046. func p256Keypair() ([]byte, []byte) {
  1047. privkey, err := ecdh.P256().GenerateKey(rand.Reader)
  1048. if err != nil {
  1049. panic(err)
  1050. }
  1051. pubkey := privkey.PublicKey()
  1052. return pubkey.Bytes(), privkey.Bytes()
  1053. }