local_test.go 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639
  1. package local
  2. import (
  3. "bytes"
  4. "crypto/ecdsa"
  5. "crypto/elliptic"
  6. "crypto/rand"
  7. "crypto/rsa"
  8. "crypto/x509"
  9. "crypto/x509/pkix"
  10. "encoding/asn1"
  11. "encoding/hex"
  12. "encoding/pem"
  13. "errors"
  14. "io/ioutil"
  15. "math/big"
  16. "net"
  17. "net/http"
  18. "net/http/httptest"
  19. "net/url"
  20. "reflect"
  21. "regexp"
  22. "sort"
  23. "strings"
  24. "testing"
  25. "time"
  26. "github.com/cloudflare/cfssl/config"
  27. "github.com/cloudflare/cfssl/csr"
  28. cferr "github.com/cloudflare/cfssl/errors"
  29. "github.com/cloudflare/cfssl/helpers"
  30. "github.com/cloudflare/cfssl/log"
  31. "github.com/cloudflare/cfssl/signer"
  32. "github.com/google/certificate-transparency-go"
  33. "github.com/zmap/zlint/v3/lint"
  34. )
  35. const (
  36. fullSubjectCSR = "testdata/test.csr"
  37. testCSR = "testdata/ecdsa256.csr"
  38. testSANCSR = "testdata/san_domain.csr"
  39. testCaFile = "testdata/ca.pem"
  40. testCaKeyFile = "testdata/ca_key.pem"
  41. testECDSACaFile = "testdata/ecdsa256_ca.pem"
  42. testECDSACaKeyFile = "testdata/ecdsa256_ca_key.pem"
  43. )
  44. var expiry = 1 * time.Minute
  45. // Start a signer with the testing RSA CA cert and key.
  46. func newTestSigner(t *testing.T) (s *Signer) {
  47. s, err := NewSignerFromFile(testCaFile, testCaKeyFile, nil)
  48. if err != nil {
  49. t.Fatal(err)
  50. }
  51. return
  52. }
  53. func TestNewSignerFromFilePolicy(t *testing.T) {
  54. var CAConfig = &config.Config{
  55. Signing: &config.Signing{
  56. Profiles: map[string]*config.SigningProfile{
  57. "signature": {
  58. Usage: []string{"digital signature"},
  59. Expiry: expiry,
  60. },
  61. },
  62. Default: &config.SigningProfile{
  63. Usage: []string{"cert sign", "crl sign"},
  64. ExpiryString: "43800h",
  65. Expiry: expiry,
  66. CAConstraint: config.CAConstraint{IsCA: true},
  67. },
  68. },
  69. }
  70. signer, err := NewSignerFromFile(testCaFile, testCaKeyFile, CAConfig.Signing)
  71. if err != nil {
  72. t.Fatal(err)
  73. }
  74. if signer.lintPriv != nil {
  75. t.Error("expected signer with LintErrLevel == 0 to have lintPriv == nil")
  76. }
  77. }
  78. func TestNewSignerFromFileInvalidPolicy(t *testing.T) {
  79. var invalidConfig = &config.Config{
  80. Signing: &config.Signing{
  81. Profiles: map[string]*config.SigningProfile{
  82. "invalid": {
  83. Usage: []string{"wiretapping"},
  84. Expiry: expiry,
  85. },
  86. "empty": {},
  87. },
  88. Default: &config.SigningProfile{
  89. Usage: []string{"digital signature"},
  90. Expiry: expiry,
  91. },
  92. },
  93. }
  94. _, err := NewSignerFromFile(testCaFile, testCaKeyFile, invalidConfig.Signing)
  95. if err == nil {
  96. t.Fatal(err)
  97. }
  98. if !strings.Contains(err.Error(), `"code":5200`) {
  99. t.Fatal(err)
  100. }
  101. }
  102. func TestNewSignerFromFileNoUsageInPolicy(t *testing.T) {
  103. var invalidConfig = &config.Config{
  104. Signing: &config.Signing{
  105. Profiles: map[string]*config.SigningProfile{
  106. "invalid": {
  107. Usage: []string{},
  108. Expiry: expiry,
  109. },
  110. "empty": {},
  111. },
  112. Default: &config.SigningProfile{
  113. Usage: []string{"digital signature"},
  114. Expiry: expiry,
  115. },
  116. },
  117. }
  118. _, err := NewSignerFromFile(testCaFile, testCaKeyFile, invalidConfig.Signing)
  119. if err == nil {
  120. t.Fatal("expect InvalidPolicy error")
  121. }
  122. if !strings.Contains(err.Error(), `"code":5200`) {
  123. t.Fatal(err)
  124. }
  125. }
  126. func TestNewSignerFromFileEdgeCases(t *testing.T) {
  127. res, err := NewSignerFromFile("nil", "nil", nil)
  128. if res != nil && err == nil {
  129. t.Fatal("Incorrect inputs failed to produce correct results")
  130. }
  131. res, err = NewSignerFromFile(testCaFile, "nil", nil)
  132. if res != nil && err == nil {
  133. t.Fatal("Incorrect inputs failed to produce correct results")
  134. }
  135. res, err = NewSignerFromFile("../../helpers/testdata/messedupcert.pem", "local.go", nil)
  136. if res != nil && err == nil {
  137. t.Fatal("Incorrect inputs failed to produce correct results")
  138. }
  139. res, err = NewSignerFromFile("../../helpers/testdata/cert.pem", "../../helpers/testdata/messed_up_priv_key.pem", nil)
  140. if res != nil && err == nil {
  141. t.Fatal("Incorrect inputs failed to produce correct results")
  142. }
  143. }
  144. func TestNewSignerFromFilePolicyLinting(t *testing.T) {
  145. // CAConfig is a config that has an explicit "signature" profile that enables
  146. // pre-issuance linting.
  147. var CAConfig = &config.Config{
  148. Signing: &config.Signing{
  149. Profiles: map[string]*config.SigningProfile{
  150. "signature": {
  151. Usage: []string{"digital signature"},
  152. Expiry: expiry,
  153. LintErrLevel: 3,
  154. },
  155. },
  156. Default: &config.SigningProfile{
  157. Usage: []string{"cert sign", "crl sign"},
  158. ExpiryString: "43800h",
  159. Expiry: expiry,
  160. CAConstraint: config.CAConstraint{IsCA: true},
  161. },
  162. },
  163. }
  164. signer, err := NewSignerFromFile(testCaFile, testCaKeyFile, CAConfig.Signing)
  165. if err != nil {
  166. t.Fatal(err)
  167. }
  168. // A CAConfig with a signing profile that sets LintErrLevel > 0 should have
  169. // a lintPriv key generated.
  170. if signer.lintPriv == nil {
  171. t.Error("expected signer with profile LintErrLevel > 0 to have lintPriv != nil")
  172. }
  173. // Reconfigure caConfig so that the explicit "signature" profile doesn't
  174. // enable pre-issuance linting but the default profile does.
  175. CAConfig.Signing.Profiles["signature"].LintErrLevel = 0
  176. CAConfig.Signing.Default.LintErrLevel = 3
  177. signer, err = NewSignerFromFile(testCaFile, testCaKeyFile, CAConfig.Signing)
  178. if err != nil {
  179. t.Fatal(err)
  180. }
  181. // A CAConfig with a default profile that sets LintErrLevel > 0 should have
  182. // a lintPriv key generated.
  183. if signer.lintPriv == nil {
  184. t.Error("expected signer with default profile LintErrLevel > 0 to have lintPriv != nil")
  185. }
  186. }
  187. func TestSign(t *testing.T) {
  188. s, err := NewSignerFromFile("testdata/ca.pem", "testdata/ca_key.pem", nil)
  189. if err != nil {
  190. t.Fatal("Failed to produce signer")
  191. }
  192. // test the empty request
  193. _, err = s.Sign(signer.SignRequest{})
  194. if err == nil {
  195. t.Fatalf("Empty request failed to produce an error")
  196. }
  197. // not a csr
  198. certPem, err := ioutil.ReadFile("../../helpers/testdata/cert.pem")
  199. if err != nil {
  200. t.Fatal(err)
  201. }
  202. // csr with ip as hostname
  203. pem, err := ioutil.ReadFile("testdata/ip.csr")
  204. if err != nil {
  205. t.Fatal(err)
  206. }
  207. // improper request
  208. validReq := signer.SignRequest{Hosts: signer.SplitHosts(testHostName), Request: string(certPem)}
  209. _, err = s.Sign(validReq)
  210. if err == nil {
  211. t.Fatal("A bad case failed to raise an error")
  212. }
  213. validReq = signer.SignRequest{Hosts: signer.SplitHosts("128.84.126.213"), Request: string(pem)}
  214. _, err = s.Sign(validReq)
  215. if err != nil {
  216. t.Fatal("A bad case failed to raise an error")
  217. }
  218. pem, err = ioutil.ReadFile("testdata/ex.csr")
  219. validReq = signer.SignRequest{
  220. Request: string(pem),
  221. Hosts: []string{"example.com"},
  222. }
  223. s.Sign(validReq)
  224. if err != nil {
  225. t.Fatal("Failed to sign")
  226. }
  227. }
  228. func TestCertificate(t *testing.T) {
  229. s, err := NewSignerFromFile("testdata/ca.pem", "testdata/ca_key.pem", nil)
  230. if err != nil {
  231. t.Fatal(err)
  232. }
  233. c, err := s.Certificate("", "")
  234. if !reflect.DeepEqual(*c, *s.ca) || err != nil {
  235. t.Fatal("Certificate() producing incorrect results")
  236. }
  237. }
  238. func TestPolicy(t *testing.T) {
  239. s, err := NewSignerFromFile("testdata/ca.pem", "testdata/ca_key.pem", nil)
  240. if err != nil {
  241. t.Fatal(err)
  242. }
  243. sgn := config.Signing{}
  244. s.SetPolicy(&sgn)
  245. if s.Policy() != &sgn {
  246. t.Fatal("Policy is malfunctioning")
  247. }
  248. }
  249. func newCustomSigner(t *testing.T, testCaFile, testCaKeyFile string) (s *Signer) {
  250. s, err := NewSignerFromFile(testCaFile, testCaKeyFile, nil)
  251. if err != nil {
  252. t.Fatal(err)
  253. }
  254. return
  255. }
  256. func TestNewSignerFromFile(t *testing.T) {
  257. newTestSigner(t)
  258. }
  259. const (
  260. testHostName = "localhost"
  261. )
  262. func testSignFile(t *testing.T, certFile string) ([]byte, error) {
  263. s := newTestSigner(t)
  264. pem, err := ioutil.ReadFile(certFile)
  265. if err != nil {
  266. t.Fatal(err)
  267. }
  268. return s.Sign(signer.SignRequest{Hosts: signer.SplitHosts(testHostName), Request: string(pem)})
  269. }
  270. type csrTest struct {
  271. file string
  272. keyAlgo string
  273. keyLen int
  274. // Error checking function
  275. errorCallback func(*testing.T, error)
  276. }
  277. // A helper function that returns a errorCallback function which expects an error.
  278. func ExpectError() func(*testing.T, error) {
  279. return func(t *testing.T, err error) {
  280. if err == nil {
  281. t.Fatal("Expected error. Got nothing.")
  282. }
  283. }
  284. }
  285. var csrTests = []csrTest{
  286. {
  287. file: "testdata/rsa2048.csr",
  288. keyAlgo: "rsa",
  289. keyLen: 2048,
  290. errorCallback: nil,
  291. },
  292. {
  293. file: "testdata/rsa3072.csr",
  294. keyAlgo: "rsa",
  295. keyLen: 3072,
  296. errorCallback: nil,
  297. },
  298. {
  299. file: "testdata/rsa4096.csr",
  300. keyAlgo: "rsa",
  301. keyLen: 4096,
  302. errorCallback: nil,
  303. },
  304. {
  305. file: "testdata/ecdsa256.csr",
  306. keyAlgo: "ecdsa",
  307. keyLen: 256,
  308. errorCallback: nil,
  309. },
  310. {
  311. file: "testdata/ecdsa384.csr",
  312. keyAlgo: "ecdsa",
  313. keyLen: 384,
  314. errorCallback: nil,
  315. },
  316. {
  317. file: "testdata/ecdsa521.csr",
  318. keyAlgo: "ecdsa",
  319. keyLen: 521,
  320. errorCallback: nil,
  321. },
  322. {
  323. file: "testdata/rsa-old.csr",
  324. keyAlgo: "rsa",
  325. keyLen: 2048,
  326. errorCallback: nil,
  327. },
  328. }
  329. func TestSignCSRs(t *testing.T) {
  330. s := newTestSigner(t)
  331. hostname := "cloudflare.com"
  332. for _, test := range csrTests {
  333. csr, err := ioutil.ReadFile(test.file)
  334. if err != nil {
  335. t.Fatal("CSR loading error:", err)
  336. }
  337. // It is possible to use different SHA2 algorithm with RSA CA key.
  338. rsaSigAlgos := []x509.SignatureAlgorithm{x509.SHA1WithRSA, x509.SHA256WithRSA, x509.SHA384WithRSA, x509.SHA512WithRSA}
  339. for _, sigAlgo := range rsaSigAlgos {
  340. s.sigAlgo = sigAlgo
  341. certBytes, err := s.Sign(signer.SignRequest{Hosts: signer.SplitHosts(hostname), Request: string(csr)})
  342. if test.errorCallback != nil {
  343. test.errorCallback(t, err)
  344. } else {
  345. if err != nil {
  346. t.Fatalf("Expected no error. Got %s. Param %s %d", err.Error(), test.keyAlgo, test.keyLen)
  347. }
  348. cert, _ := helpers.ParseCertificatePEM(certBytes)
  349. if cert.SignatureAlgorithm != s.SigAlgo() {
  350. t.Fatal("Cert Signature Algorithm does not match the issuer.")
  351. }
  352. }
  353. }
  354. }
  355. }
  356. func TestECDSASigner(t *testing.T) {
  357. s := newCustomSigner(t, testECDSACaFile, testECDSACaKeyFile)
  358. hostname := "cloudflare.com"
  359. for _, test := range csrTests {
  360. csr, err := ioutil.ReadFile(test.file)
  361. if err != nil {
  362. t.Fatal("CSR loading error:", err)
  363. }
  364. // Try all ECDSA SignatureAlgorithm
  365. SigAlgos := []x509.SignatureAlgorithm{x509.ECDSAWithSHA1, x509.ECDSAWithSHA256, x509.ECDSAWithSHA384, x509.ECDSAWithSHA512}
  366. for _, sigAlgo := range SigAlgos {
  367. s.sigAlgo = sigAlgo
  368. certBytes, err := s.Sign(signer.SignRequest{Hosts: signer.SplitHosts(hostname), Request: string(csr)})
  369. if test.errorCallback != nil {
  370. test.errorCallback(t, err)
  371. } else {
  372. if err != nil {
  373. t.Fatalf("Expected no error. Got %s. Param %s %d", err.Error(), test.keyAlgo, test.keyLen)
  374. }
  375. cert, _ := helpers.ParseCertificatePEM(certBytes)
  376. if cert.SignatureAlgorithm != s.SigAlgo() {
  377. t.Fatal("Cert Signature Algorithm does not match the issuer.")
  378. }
  379. }
  380. }
  381. }
  382. }
  383. const (
  384. ecdsaInterCSR = "testdata/ecdsa256-inter.csr"
  385. ecdsaInterKey = "testdata/ecdsa256-inter.key"
  386. rsaInterCSR = "testdata/rsa2048-inter.csr"
  387. rsaInterKey = "testdata/rsa2048-inter.key"
  388. )
  389. func TestCAIssuing(t *testing.T) {
  390. var caCerts = []string{testCaFile, testECDSACaFile}
  391. var caKeys = []string{testCaKeyFile, testECDSACaKeyFile}
  392. var interCSRs = []string{ecdsaInterCSR, rsaInterCSR}
  393. var interKeys = []string{ecdsaInterKey, rsaInterKey}
  394. var CAPolicy = &config.Signing{
  395. Default: &config.SigningProfile{
  396. Usage: []string{"cert sign", "crl sign"},
  397. ExpiryString: "1h",
  398. Expiry: 1 * time.Hour,
  399. CAConstraint: config.CAConstraint{IsCA: true, MaxPathLenZero: true},
  400. },
  401. }
  402. var hostname = "cloudflare-inter.com"
  403. // Each RSA or ECDSA root CA issues two intermediate CAs (one ECDSA and one RSA).
  404. // For each intermediate CA, use it to issue additional RSA and ECDSA intermediate CSRs.
  405. for i, caFile := range caCerts {
  406. caKeyFile := caKeys[i]
  407. s := newCustomSigner(t, caFile, caKeyFile)
  408. s.policy = CAPolicy
  409. for j, csr := range interCSRs {
  410. csrBytes, _ := ioutil.ReadFile(csr)
  411. certBytes, err := s.Sign(signer.SignRequest{Hosts: signer.SplitHosts(hostname), Request: string(csrBytes)})
  412. if err != nil {
  413. t.Fatal(err)
  414. }
  415. interCert, err := helpers.ParseCertificatePEM(certBytes)
  416. if err != nil {
  417. t.Fatal(err)
  418. }
  419. keyBytes, _ := ioutil.ReadFile(interKeys[j])
  420. interKey, _ := helpers.ParsePrivateKeyPEM(keyBytes)
  421. interSigner := &Signer{
  422. ca: interCert,
  423. priv: interKey,
  424. policy: CAPolicy,
  425. sigAlgo: signer.DefaultSigAlgo(interKey),
  426. }
  427. for _, anotherCSR := range interCSRs {
  428. anotherCSRBytes, _ := ioutil.ReadFile(anotherCSR)
  429. bytes, err := interSigner.Sign(
  430. signer.SignRequest{
  431. Hosts: signer.SplitHosts(hostname),
  432. Request: string(anotherCSRBytes),
  433. })
  434. if err != nil {
  435. t.Fatal(err)
  436. }
  437. cert, err := helpers.ParseCertificatePEM(bytes)
  438. if err != nil {
  439. t.Fatal(err)
  440. }
  441. if cert.SignatureAlgorithm != interSigner.SigAlgo() {
  442. t.Fatal("Cert Signature Algorithm does not match the issuer.")
  443. }
  444. if cert.MaxPathLen != 0 {
  445. t.Fatal("CA Cert Max Path is not zero.")
  446. }
  447. if cert.MaxPathLenZero != true {
  448. t.Fatal("CA Cert Max Path is not zero.")
  449. }
  450. }
  451. }
  452. }
  453. }
  454. func TestPopulateSubjectFromCSR(t *testing.T) {
  455. // a subject with all its fields full.
  456. fullSubject := &signer.Subject{
  457. CN: "CN",
  458. Names: []csr.Name{
  459. {
  460. C: "C",
  461. ST: "ST",
  462. L: "L",
  463. O: "O",
  464. OU: "OU",
  465. },
  466. },
  467. SerialNumber: "deadbeef",
  468. }
  469. fullName := pkix.Name{
  470. CommonName: "CommonName",
  471. Country: []string{"Country"},
  472. Province: []string{"Province"},
  473. Organization: []string{"Organization"},
  474. OrganizationalUnit: []string{"OrganizationalUnit"},
  475. SerialNumber: "SerialNumber",
  476. }
  477. noCN := *fullSubject
  478. noCN.CN = ""
  479. name := PopulateSubjectFromCSR(&noCN, fullName)
  480. if name.CommonName != "CommonName" {
  481. t.Fatal("Failed to replace empty common name")
  482. }
  483. noC := *fullSubject
  484. noC.Names[0].C = ""
  485. name = PopulateSubjectFromCSR(&noC, fullName)
  486. if !reflect.DeepEqual(name.Country, fullName.Country) {
  487. t.Fatal("Failed to replace empty country")
  488. }
  489. noL := *fullSubject
  490. noL.Names[0].L = ""
  491. name = PopulateSubjectFromCSR(&noL, fullName)
  492. if !reflect.DeepEqual(name.Locality, fullName.Locality) {
  493. t.Fatal("Failed to replace empty locality")
  494. }
  495. noO := *fullSubject
  496. noO.Names[0].O = ""
  497. name = PopulateSubjectFromCSR(&noO, fullName)
  498. if !reflect.DeepEqual(name.Organization, fullName.Organization) {
  499. t.Fatal("Failed to replace empty organization")
  500. }
  501. noOU := *fullSubject
  502. noOU.Names[0].OU = ""
  503. name = PopulateSubjectFromCSR(&noOU, fullName)
  504. if !reflect.DeepEqual(name.OrganizationalUnit, fullName.OrganizationalUnit) {
  505. t.Fatal("Failed to replace empty organizational unit")
  506. }
  507. noSerial := *fullSubject
  508. noSerial.SerialNumber = ""
  509. name = PopulateSubjectFromCSR(&noSerial, fullName)
  510. if name.SerialNumber != fullName.SerialNumber {
  511. t.Fatalf("Failed to replace empty serial number: want %#v, got %#v", fullName.SerialNumber, name.SerialNumber)
  512. }
  513. }
  514. func TestOverrideSubject(t *testing.T) {
  515. csrPEM, err := ioutil.ReadFile(fullSubjectCSR)
  516. if err != nil {
  517. t.Fatalf("%v", err)
  518. }
  519. req := &signer.Subject{
  520. Names: []csr.Name{
  521. {O: "example.net"},
  522. },
  523. }
  524. s := newCustomSigner(t, testECDSACaFile, testECDSACaKeyFile)
  525. request := signer.SignRequest{
  526. Hosts: []string{"127.0.0.1", "localhost", "xyz@example.com", "https://www.cloudflare.com"},
  527. Request: string(csrPEM),
  528. Subject: req,
  529. }
  530. certPEM, err := s.Sign(request)
  531. if err != nil {
  532. t.Fatalf("%v", err)
  533. }
  534. cert, err := helpers.ParseCertificatePEM(certPEM)
  535. if err != nil {
  536. t.Fatalf("%v", err)
  537. }
  538. block, _ := pem.Decode(csrPEM)
  539. template, err := x509.ParseCertificateRequest(block.Bytes)
  540. if err != nil {
  541. t.Fatal(err.Error())
  542. }
  543. if cert.Subject.Organization[0] != "example.net" {
  544. t.Fatalf("Failed to override subject: want example.net but have %s", cert.Subject.Organization[0])
  545. }
  546. if cert.Subject.Country[0] != template.Subject.Country[0] {
  547. t.Fatal("Failed to override Country")
  548. }
  549. if cert.Subject.Locality[0] != template.Subject.Locality[0] {
  550. t.Fatal("Failed to override Locality")
  551. }
  552. if cert.Subject.Organization[0] == template.Subject.Organization[0] {
  553. t.Fatal("Shouldn't have overrode Organization")
  554. }
  555. if cert.Subject.OrganizationalUnit[0] != template.Subject.OrganizationalUnit[0] {
  556. t.Fatal("Failed to override OrganizationalUnit")
  557. }
  558. log.Info("Overrode subject info")
  559. }
  560. func TestOverwriteHosts(t *testing.T) {
  561. for _, csrFile := range []string{testCSR, testSANCSR} {
  562. csrPEM, err := ioutil.ReadFile(csrFile)
  563. if err != nil {
  564. t.Fatal(err)
  565. }
  566. csrDER, _ := pem.Decode([]byte(csrPEM))
  567. if err != nil {
  568. t.Fatal(err)
  569. }
  570. csr, err := x509.ParseCertificateRequest(csrDER.Bytes)
  571. if err != nil {
  572. t.Fatal(err)
  573. }
  574. csrHosts := csr.DNSNames
  575. for _, ip := range csr.IPAddresses {
  576. csrHosts = append(csrHosts, ip.String())
  577. }
  578. sort.Strings(csrHosts)
  579. s := newCustomSigner(t, testECDSACaFile, testECDSACaKeyFile)
  580. for _, hosts := range [][]string{
  581. nil,
  582. {},
  583. {"127.0.0.1", "localhost", "xyz@example.com", "https://www.cloudflare.com"},
  584. } {
  585. request := signer.SignRequest{
  586. Hosts: hosts,
  587. Request: string(csrPEM),
  588. Subject: nil,
  589. }
  590. certPEM, err := s.Sign(request)
  591. if err != nil {
  592. t.Fatalf("%v", err)
  593. }
  594. cert, err := helpers.ParseCertificatePEM(certPEM)
  595. if err != nil {
  596. t.Fatalf("%v", err)
  597. }
  598. // get the hosts, and add the ips and email addresses
  599. certHosts := cert.DNSNames
  600. for _, ip := range cert.IPAddresses {
  601. certHosts = append(certHosts, ip.String())
  602. }
  603. for _, email := range cert.EmailAddresses {
  604. certHosts = append(certHosts, email)
  605. }
  606. for _, uri := range cert.URIs {
  607. certHosts = append(certHosts, uri.String())
  608. }
  609. // compare the sorted host lists
  610. sort.Strings(certHosts)
  611. sort.Strings(request.Hosts)
  612. if len(request.Hosts) > 0 && !reflect.DeepEqual(certHosts, request.Hosts) {
  613. t.Fatalf("Hosts not the same. cert hosts: %v, expected: %v", certHosts, request.Hosts)
  614. }
  615. if request.Hosts == nil && !reflect.DeepEqual(certHosts, csrHosts) {
  616. t.Fatalf("Hosts not the same. cert hosts: %v, expected csr hosts: %v", certHosts, csrHosts)
  617. }
  618. if request.Hosts != nil && len(request.Hosts) == 0 && len(certHosts) != 0 {
  619. t.Fatalf("Hosts not the same. cert hosts: %v, expected: %v", certHosts, request.Hosts)
  620. }
  621. }
  622. }
  623. }
  624. func TestOverrideValidity(t *testing.T) {
  625. csrPEM, err := ioutil.ReadFile(fullSubjectCSR)
  626. if err != nil {
  627. t.Fatalf("%v", err)
  628. }
  629. s := newCustomSigner(t, testECDSACaFile, testECDSACaKeyFile)
  630. req := signer.SignRequest{
  631. Request: string(csrPEM),
  632. }
  633. // The default expiry value.
  634. expiry := 8760 * time.Hour
  635. // default case
  636. now := time.Now().UTC()
  637. certPEM, err := s.Sign(req)
  638. if err != nil {
  639. t.Fatalf("Error signing default request: %s", err)
  640. }
  641. cert, err := helpers.ParseCertificatePEM(certPEM)
  642. if err != nil {
  643. t.Fatalf("%v", err)
  644. }
  645. if !cert.NotBefore.After(now.Add(-10*time.Minute)) || !cert.NotBefore.Before(now.Add(10*time.Minute)) {
  646. t.Fatalf("Unexpected NotBefore: wanted %s +/-10 minutes, got %s", now, cert.NotBefore)
  647. }
  648. expectedNotAfter := now.Round(time.Minute).Add(expiry)
  649. if !cert.NotAfter.After(expectedNotAfter.Add(-10*time.Minute)) || !cert.NotAfter.Before(expectedNotAfter.Add(10*time.Minute)) {
  650. t.Fatalf("Unexpected NotAfter: wanted %s +/-10 minutes, got %s", now, cert.NotAfter)
  651. }
  652. // custom case, NotBefore only
  653. now = time.Now().UTC()
  654. req.NotBefore = now.Add(-time.Hour * 5).Truncate(time.Hour)
  655. req.NotAfter = time.Time{}
  656. certPEM, err = s.Sign(req)
  657. if err != nil {
  658. t.Fatalf("Error signing default request: %s", err)
  659. }
  660. cert, err = helpers.ParseCertificatePEM(certPEM)
  661. if err != nil {
  662. t.Fatalf("%v", err)
  663. }
  664. if !cert.NotBefore.Equal(req.NotBefore) {
  665. t.Fatalf("Unexpected NotBefore: wanted %s, got %s", req.NotBefore, cert.NotBefore)
  666. }
  667. expectedNotAfter = req.NotBefore.Add(expiry)
  668. if !cert.NotAfter.After(expectedNotAfter.Add(-10*time.Minute)) || !cert.NotAfter.Before(expectedNotAfter.Add(10*time.Minute)) {
  669. t.Fatalf("Unexpected NotAfter: wanted %s +/-10 minutes, got %s", expectedNotAfter, cert.NotAfter)
  670. }
  671. // custom case, NotAfter only
  672. now = time.Now().UTC()
  673. req.NotBefore = time.Time{}
  674. req.NotAfter = now.Add(-time.Hour * 5).Truncate(time.Hour)
  675. certPEM, err = s.Sign(req)
  676. if err != nil {
  677. t.Fatalf("Error signing default request: %s", err)
  678. }
  679. cert, err = helpers.ParseCertificatePEM(certPEM)
  680. if err != nil {
  681. t.Fatalf("%v", err)
  682. }
  683. if !cert.NotBefore.After(now.Add(-10*time.Minute)) || !cert.NotBefore.Before(now.Add(10*time.Minute)) {
  684. t.Fatalf("Unexpected NotBefore: wanted %s +/-10 minutes, got %s", now, cert.NotBefore)
  685. }
  686. if !cert.NotAfter.Equal(req.NotAfter) {
  687. t.Fatalf("Unexpected NotAfter: wanted %s, got %s", req.NotAfter, cert.NotAfter)
  688. }
  689. // custom case, NotBefore and NotAfter
  690. now = time.Now().UTC()
  691. req.NotBefore = now.Add(-time.Hour * 5).Truncate(time.Hour)
  692. req.NotAfter = now.Add(time.Hour * 5).Truncate(time.Hour)
  693. certPEM, err = s.Sign(req)
  694. if err != nil {
  695. t.Fatalf("Error signing default request: %s", err)
  696. }
  697. cert, err = helpers.ParseCertificatePEM(certPEM)
  698. if err != nil {
  699. t.Fatalf("%v", err)
  700. }
  701. if !cert.NotBefore.Equal(req.NotBefore) {
  702. t.Fatalf("Unexpected NotBefore: wanted %s, got %s", req.NotBefore, cert.NotBefore)
  703. }
  704. if !cert.NotAfter.Equal(req.NotAfter) {
  705. t.Fatalf("Unexpected NotAfter: wanted %s, got %s", req.NotAfter, cert.NotAfter)
  706. }
  707. }
  708. func expectOneValueOf(t *testing.T, s []string, e, n string) {
  709. if len(s) != 1 {
  710. t.Fatalf("Expected %s to have a single value, but it has %d values", n, len(s))
  711. }
  712. if s[0] != e {
  713. t.Fatalf("Expected %s to be '%s', but it is '%s'", n, e, s[0])
  714. }
  715. }
  716. func expectEmpty(t *testing.T, s []string, n string) {
  717. if len(s) != 0 {
  718. t.Fatalf("Expected no values in %s, but have %d values: %v", n, len(s), s)
  719. }
  720. }
  721. func TestCASignPathlen(t *testing.T) {
  722. var csrPathlenTests = []struct {
  723. name string
  724. caCertFile string
  725. caKeyFile string
  726. caProfile bool
  727. csrFile string
  728. err error
  729. pathlen int
  730. isZero bool
  731. isCA bool
  732. }{
  733. {
  734. name: "pathlen 1 signing pathlen 0",
  735. caCertFile: testECDSACaFile,
  736. caKeyFile: testECDSACaKeyFile,
  737. caProfile: true,
  738. csrFile: "testdata/inter_pathlen_0.csr",
  739. err: nil,
  740. pathlen: 0,
  741. isZero: true,
  742. isCA: true,
  743. },
  744. {
  745. name: "pathlen 1 signing pathlen 1",
  746. caCertFile: testECDSACaFile,
  747. caKeyFile: testECDSACaKeyFile,
  748. caProfile: true,
  749. csrFile: "testdata/inter_pathlen_1.csr",
  750. err: cferr.New(cferr.PolicyError, cferr.InvalidRequest),
  751. },
  752. {
  753. name: "pathlen 0 signing pathlen 0",
  754. caCertFile: testCaFile,
  755. caKeyFile: testCaKeyFile,
  756. caProfile: true,
  757. csrFile: "testdata/inter_pathlen_0.csr",
  758. err: cferr.New(cferr.PolicyError, cferr.InvalidRequest),
  759. },
  760. {
  761. name: "pathlen 0 signing pathlen 1",
  762. caCertFile: testCaFile,
  763. caKeyFile: testCaKeyFile,
  764. caProfile: true,
  765. csrFile: "testdata/inter_pathlen_1.csr",
  766. err: cferr.New(cferr.PolicyError, cferr.InvalidRequest),
  767. },
  768. {
  769. name: "pathlen 0 signing pathlen unspecified",
  770. caCertFile: testCaFile,
  771. caKeyFile: testCaKeyFile,
  772. caProfile: true,
  773. csrFile: "testdata/inter_pathlen_unspecified.csr",
  774. err: cferr.New(cferr.PolicyError, cferr.InvalidRequest),
  775. },
  776. {
  777. name: "pathlen 1 signing unspecified pathlen",
  778. caCertFile: testECDSACaFile,
  779. caKeyFile: testECDSACaKeyFile,
  780. caProfile: true,
  781. csrFile: "testdata/inter_pathlen_unspecified.csr",
  782. err: nil,
  783. // golang x509 parses unspecified pathlen as MaxPathLen == -1 and
  784. // MaxPathLenZero == false
  785. pathlen: -1,
  786. isZero: false,
  787. isCA: true,
  788. },
  789. {
  790. name: "non-ca singing profile signing pathlen 0",
  791. caCertFile: testECDSACaFile,
  792. caKeyFile: testECDSACaKeyFile,
  793. caProfile: false,
  794. csrFile: "testdata/inter_pathlen_0.csr",
  795. err: cferr.New(cferr.PolicyError, cferr.InvalidRequest),
  796. },
  797. {
  798. name: "non-ca singing profile signing pathlen 1",
  799. caCertFile: testECDSACaFile,
  800. caKeyFile: testECDSACaKeyFile,
  801. caProfile: false,
  802. csrFile: "testdata/inter_pathlen_1.csr",
  803. err: cferr.New(cferr.PolicyError, cferr.InvalidRequest),
  804. },
  805. {
  806. name: "non-ca singing profile signing pathlen 0",
  807. caCertFile: testECDSACaFile,
  808. caKeyFile: testECDSACaKeyFile,
  809. caProfile: false,
  810. csrFile: "testdata/inter_pathlen_unspecified.csr",
  811. err: cferr.New(cferr.PolicyError, cferr.InvalidRequest),
  812. },
  813. }
  814. for _, testCase := range csrPathlenTests {
  815. csrPEM, err := ioutil.ReadFile(testCase.csrFile)
  816. if err != nil {
  817. t.Fatalf("%v", err)
  818. }
  819. req := &signer.Subject{
  820. Names: []csr.Name{
  821. {O: "sam certificate authority"},
  822. },
  823. CN: "localhost",
  824. }
  825. s := newCustomSigner(t, testCase.caCertFile, testCase.caKeyFile)
  826. // No policy CSR whitelist: the normal set of CSR fields get passed through to
  827. // certificate.
  828. s.policy = &config.Signing{
  829. Default: &config.SigningProfile{
  830. Usage: []string{"cert sign", "crl sign"},
  831. ExpiryString: "1h",
  832. Expiry: 1 * time.Hour,
  833. CAConstraint: config.CAConstraint{IsCA: testCase.caProfile,
  834. MaxPathLen: testCase.pathlen,
  835. MaxPathLenZero: testCase.isZero,
  836. },
  837. },
  838. }
  839. request := signer.SignRequest{
  840. Hosts: []string{"127.0.0.1", "localhost"},
  841. Request: string(csrPEM),
  842. Subject: req,
  843. }
  844. certPEM, err := s.Sign(request)
  845. if !reflect.DeepEqual(err, testCase.err) {
  846. t.Fatalf("%s: expected: %v, actual: %v", testCase.name, testCase.err, err)
  847. }
  848. if err == nil {
  849. cert, err := helpers.ParseCertificatePEM(certPEM)
  850. if err != nil {
  851. t.Fatalf("%s: %v", testCase.name, err)
  852. }
  853. if cert.IsCA != testCase.isCA {
  854. t.Fatalf("%s: unexpected IsCA value: %v", testCase.name, cert.IsCA)
  855. }
  856. if cert.MaxPathLen != testCase.pathlen {
  857. t.Fatalf("%s: unexpected pathlen value: %v", testCase.name, cert.MaxPathLen)
  858. }
  859. if cert.MaxPathLenZero != testCase.isZero {
  860. t.Fatalf("%s: unexpected pathlen value: %v", testCase.name, cert.MaxPathLenZero)
  861. }
  862. }
  863. }
  864. }
  865. func TestNoWhitelistSign(t *testing.T) {
  866. csrPEM, err := ioutil.ReadFile(fullSubjectCSR)
  867. if err != nil {
  868. t.Fatalf("%v", err)
  869. }
  870. req := &signer.Subject{
  871. Names: []csr.Name{
  872. {O: "sam certificate authority"},
  873. },
  874. CN: "localhost",
  875. }
  876. s := newCustomSigner(t, testECDSACaFile, testECDSACaKeyFile)
  877. // No policy CSR whitelist: the normal set of CSR fields get passed through to
  878. // certificate.
  879. s.policy = &config.Signing{
  880. Default: &config.SigningProfile{
  881. Usage: []string{"cert sign", "crl sign"},
  882. ExpiryString: "1h",
  883. Expiry: 1 * time.Hour,
  884. CAConstraint: config.CAConstraint{IsCA: true},
  885. },
  886. }
  887. request := signer.SignRequest{
  888. Hosts: []string{"127.0.0.1", "localhost"},
  889. Request: string(csrPEM),
  890. Subject: req,
  891. }
  892. certPEM, err := s.Sign(request)
  893. if err != nil {
  894. t.Fatalf("%v", err)
  895. }
  896. cert, err := helpers.ParseCertificatePEM(certPEM)
  897. if err != nil {
  898. t.Fatalf("%v", err)
  899. }
  900. name := cert.Subject
  901. if name.CommonName != "localhost" {
  902. t.Fatalf("Expected certificate common name to be 'localhost' but have '%v'", name.CommonName)
  903. }
  904. // CSR has: Subject: C=US, O=CloudFlare, OU=WWW, L=Ithaca, ST=New York
  905. // Expect all to be passed through.
  906. expectOneValueOf(t, name.Organization, "sam certificate authority", "O")
  907. expectOneValueOf(t, name.OrganizationalUnit, "WWW", "OU")
  908. expectOneValueOf(t, name.Province, "New York", "ST")
  909. expectOneValueOf(t, name.Locality, "Ithaca", "L")
  910. expectOneValueOf(t, name.Country, "US", "C")
  911. }
  912. func TestWhitelistSign(t *testing.T) {
  913. csrPEM, err := ioutil.ReadFile(fullSubjectCSR)
  914. if err != nil {
  915. t.Fatalf("%v", err)
  916. }
  917. req := &signer.Subject{
  918. Names: []csr.Name{
  919. {O: "sam certificate authority"},
  920. },
  921. }
  922. s := newCustomSigner(t, testECDSACaFile, testECDSACaKeyFile)
  923. // Whitelist only key-related fields. Subject, DNSNames, etc shouldn't get
  924. // passed through from CSR.
  925. s.policy = &config.Signing{
  926. Default: &config.SigningProfile{
  927. Usage: []string{"cert sign", "crl sign"},
  928. ExpiryString: "1h",
  929. Expiry: 1 * time.Hour,
  930. CAConstraint: config.CAConstraint{IsCA: true},
  931. CSRWhitelist: &config.CSRWhitelist{
  932. PublicKey: true,
  933. PublicKeyAlgorithm: true,
  934. SignatureAlgorithm: true,
  935. },
  936. },
  937. }
  938. request := signer.SignRequest{
  939. Hosts: []string{"127.0.0.1", "localhost"},
  940. Request: string(csrPEM),
  941. Subject: req,
  942. }
  943. certPEM, err := s.Sign(request)
  944. if err != nil {
  945. t.Fatalf("%v", err)
  946. }
  947. cert, err := helpers.ParseCertificatePEM(certPEM)
  948. if err != nil {
  949. t.Fatalf("%v", err)
  950. }
  951. name := cert.Subject
  952. if name.CommonName != "" {
  953. t.Fatalf("Expected empty certificate common name under policy without "+
  954. "Subject whitelist, got %v", name.CommonName)
  955. }
  956. // O is provided by the signing API request, not the CSR, so it's allowed to
  957. // be copied into the certificate.
  958. expectOneValueOf(t, name.Organization, "sam certificate authority", "O")
  959. expectEmpty(t, name.OrganizationalUnit, "OU")
  960. expectEmpty(t, name.Province, "ST")
  961. expectEmpty(t, name.Locality, "L")
  962. expectEmpty(t, name.Country, "C")
  963. if cert.PublicKeyAlgorithm != x509.RSA {
  964. t.Fatalf("Expected public key algorithm to be RSA")
  965. }
  966. // Signature algorithm is allowed to be copied from CSR, but is overridden by
  967. // DefaultSigAlgo.
  968. if cert.SignatureAlgorithm != x509.ECDSAWithSHA256 {
  969. t.Fatalf("Expected public key algorithm to be ECDSAWithSHA256, got %v",
  970. cert.SignatureAlgorithm)
  971. }
  972. }
  973. func TestNameWhitelistSign(t *testing.T) {
  974. csrPEM, err := ioutil.ReadFile(fullSubjectCSR)
  975. if err != nil {
  976. t.Fatalf("%v", err)
  977. }
  978. subInvalid := &signer.Subject{
  979. CN: "localhost.com",
  980. }
  981. subValid := &signer.Subject{
  982. CN: "1lab41.cf",
  983. }
  984. wl := regexp.MustCompile("^1[a-z]*[0-9]*\\.cf$")
  985. s := newCustomSigner(t, testECDSACaFile, testECDSACaKeyFile)
  986. // Whitelist only key-related fields. Subject, DNSNames, etc shouldn't get
  987. // passed through from CSR.
  988. s.policy = &config.Signing{
  989. Default: &config.SigningProfile{
  990. Usage: []string{"cert sign", "crl sign"},
  991. ExpiryString: "1h",
  992. Expiry: 1 * time.Hour,
  993. CAConstraint: config.CAConstraint{IsCA: true},
  994. NameWhitelist: wl,
  995. },
  996. }
  997. request := signer.SignRequest{
  998. Hosts: []string{"127.0.0.1", "1machine23.cf"},
  999. Request: string(csrPEM),
  1000. }
  1001. _, err = s.Sign(request)
  1002. if err != nil {
  1003. t.Fatalf("%v", err)
  1004. }
  1005. request = signer.SignRequest{
  1006. Hosts: []string{"invalid.cf", "1machine23.cf"},
  1007. Request: string(csrPEM),
  1008. }
  1009. _, err = s.Sign(request)
  1010. if err == nil {
  1011. t.Fatalf("expected a policy error")
  1012. }
  1013. request = signer.SignRequest{
  1014. Hosts: []string{"1machine23.cf"},
  1015. Request: string(csrPEM),
  1016. Subject: subInvalid,
  1017. }
  1018. _, err = s.Sign(request)
  1019. if err == nil {
  1020. t.Fatalf("expected a policy error")
  1021. }
  1022. request = signer.SignRequest{
  1023. Hosts: []string{"1machine23.cf"},
  1024. Request: string(csrPEM),
  1025. Subject: subValid,
  1026. }
  1027. _, err = s.Sign(request)
  1028. if err != nil {
  1029. t.Fatalf("%v", err)
  1030. }
  1031. }
  1032. func TestExtensionSign(t *testing.T) {
  1033. csrPEM, err := ioutil.ReadFile(testCSR)
  1034. if err != nil {
  1035. t.Fatalf("%v", err)
  1036. }
  1037. s := newCustomSigner(t, testECDSACaFile, testECDSACaKeyFile)
  1038. // By default, no extensions should be allowed
  1039. request := signer.SignRequest{
  1040. Request: string(csrPEM),
  1041. Extensions: []signer.Extension{
  1042. {ID: config.OID(asn1.ObjectIdentifier{1, 2, 3, 4})},
  1043. },
  1044. }
  1045. _, err = s.Sign(request)
  1046. if err == nil {
  1047. t.Fatalf("expected a policy error")
  1048. }
  1049. // Whitelist a specific extension. The extension with OID 1.2.3.4 should be
  1050. // allowed through, but the one with OID 1.2.3.5 should not.
  1051. s.policy = &config.Signing{
  1052. Default: &config.SigningProfile{
  1053. Usage: []string{"cert sign", "crl sign"},
  1054. ExpiryString: "1h",
  1055. Expiry: 1 * time.Hour,
  1056. CAConstraint: config.CAConstraint{IsCA: true},
  1057. ExtensionWhitelist: map[string]bool{"1.2.3.4": true},
  1058. },
  1059. }
  1060. // Test that a forbidden extension triggers a sign error
  1061. request = signer.SignRequest{
  1062. Request: string(csrPEM),
  1063. Extensions: []signer.Extension{
  1064. {ID: config.OID(asn1.ObjectIdentifier{1, 2, 3, 5})},
  1065. },
  1066. }
  1067. _, err = s.Sign(request)
  1068. if err == nil {
  1069. t.Fatalf("expected a policy error")
  1070. }
  1071. extValue := []byte{0x05, 0x00}
  1072. extValueHex := hex.EncodeToString(extValue)
  1073. // Test that an allowed extension makes it through
  1074. request = signer.SignRequest{
  1075. Request: string(csrPEM),
  1076. Extensions: []signer.Extension{
  1077. {
  1078. ID: config.OID(asn1.ObjectIdentifier{1, 2, 3, 4}),
  1079. Critical: false,
  1080. Value: extValueHex,
  1081. },
  1082. },
  1083. }
  1084. certPEM, err := s.Sign(request)
  1085. if err != nil {
  1086. t.Fatalf("%v", err)
  1087. }
  1088. cert, err := helpers.ParseCertificatePEM(certPEM)
  1089. if err != nil {
  1090. t.Fatalf("%v", err)
  1091. }
  1092. foundAllowed := false
  1093. for _, ext := range cert.Extensions {
  1094. if ext.Id.String() == "1.2.3.4" {
  1095. foundAllowed = true
  1096. if ext.Critical {
  1097. t.Fatalf("Extensions should not be marked critical")
  1098. }
  1099. if !bytes.Equal(extValue, ext.Value) {
  1100. t.Fatalf("Extension has wrong value: %s != %s", hex.EncodeToString(ext.Value), extValueHex)
  1101. }
  1102. }
  1103. }
  1104. if !foundAllowed {
  1105. t.Fatalf("Custom extension not included in the certificate")
  1106. }
  1107. }
  1108. func TestCTFailure(t *testing.T) {
  1109. // start a fake CT server that returns bad request
  1110. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1111. w.WriteHeader(400)
  1112. }))
  1113. defer ts.Close()
  1114. var config = &config.Signing{
  1115. Default: &config.SigningProfile{
  1116. Expiry: helpers.OneYear,
  1117. CAConstraint: config.CAConstraint{IsCA: true},
  1118. Usage: []string{"signing", "key encipherment", "server auth", "client auth"},
  1119. ExpiryString: "8760h",
  1120. CTLogServers: []string{ts.URL},
  1121. },
  1122. }
  1123. testSigner, err := NewSignerFromFile(testCaFile, testCaKeyFile, config)
  1124. if err != nil {
  1125. t.Fatalf("%v", err)
  1126. }
  1127. var pem []byte
  1128. pem, err = ioutil.ReadFile("testdata/ex.csr")
  1129. if err != nil {
  1130. t.Fatalf("%v", err)
  1131. }
  1132. validReq := signer.SignRequest{
  1133. Request: string(pem),
  1134. Hosts: []string{"example.com"},
  1135. }
  1136. _, err = testSigner.Sign(validReq)
  1137. if err == nil {
  1138. t.Fatal("Expected CT log submission failure")
  1139. }
  1140. }
  1141. func TestCTSuccess(t *testing.T) {
  1142. // start a fake CT server that will accept the submission
  1143. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1144. w.Write([]byte(`{"sct_version":0,"id":"KHYaGJAn++880NYaAY12sFBXKcenQRvMvfYE9F1CYVM=","timestamp":1337,"extensions":"","signature":"BAMARjBEAiAIc21J5ZbdKZHw5wLxCP+MhBEsV5+nfvGyakOIv6FOvAIgWYMZb6Pw///uiNM7QTg2Of1OqmK1GbeGuEl9VJN8v8c="}`))
  1145. w.WriteHeader(200)
  1146. }))
  1147. defer ts.Close()
  1148. var config = &config.Signing{
  1149. Default: &config.SigningProfile{
  1150. Expiry: helpers.OneYear,
  1151. CAConstraint: config.CAConstraint{IsCA: true},
  1152. Usage: []string{"signing", "key encipherment", "server auth", "client auth"},
  1153. ExpiryString: "8760h",
  1154. CTLogServers: []string{ts.URL},
  1155. },
  1156. }
  1157. testSigner, err := NewSignerFromFile(testCaFile, testCaKeyFile, config)
  1158. if err != nil {
  1159. t.Fatalf("%v", err)
  1160. }
  1161. var pem []byte
  1162. pem, err = ioutil.ReadFile("testdata/ex.csr")
  1163. if err != nil {
  1164. t.Fatalf("%v", err)
  1165. }
  1166. validReq := signer.SignRequest{
  1167. Request: string(pem),
  1168. Hosts: []string{"example.com"},
  1169. }
  1170. _, err = testSigner.Sign(validReq)
  1171. if err != nil {
  1172. t.Fatal("Expected CT log submission success")
  1173. }
  1174. }
  1175. func TestReturnPrecert(t *testing.T) {
  1176. var config = &config.Signing{
  1177. Default: &config.SigningProfile{
  1178. Expiry: helpers.OneYear,
  1179. CAConstraint: config.CAConstraint{IsCA: true},
  1180. Usage: []string{"signing", "key encipherment", "server auth", "client auth"},
  1181. ExpiryString: "8760h",
  1182. },
  1183. }
  1184. testSigner, err := NewSignerFromFile(testCaFile, testCaKeyFile, config)
  1185. if err != nil {
  1186. t.Fatalf("%v", err)
  1187. }
  1188. csr, err := ioutil.ReadFile("testdata/ex.csr")
  1189. if err != nil {
  1190. t.Fatalf("%v", err)
  1191. }
  1192. validReq := signer.SignRequest{
  1193. Request: string(csr),
  1194. Hosts: []string{"example.com"},
  1195. ReturnPrecert: true,
  1196. }
  1197. certBytes, err := testSigner.Sign(validReq)
  1198. if err != nil {
  1199. t.Fatal("Failed to sign request")
  1200. }
  1201. block, _ := pem.Decode(certBytes)
  1202. cert, err := x509.ParseCertificate(block.Bytes)
  1203. if err != nil {
  1204. t.Fatalf("Failed to parse signed cert: %s", err)
  1205. }
  1206. // check cert with poison extension was returned
  1207. poisoned := false
  1208. for _, ext := range cert.Extensions {
  1209. if ext.Id.Equal(signer.CTPoisonOID) {
  1210. poisoned = true
  1211. break
  1212. }
  1213. }
  1214. if !poisoned {
  1215. t.Fatal("Certificate without poison CT extension was returned")
  1216. }
  1217. }
  1218. func TestSignFromPrecert(t *testing.T) {
  1219. var config = &config.Signing{
  1220. Default: &config.SigningProfile{
  1221. Expiry: helpers.OneYear,
  1222. CAConstraint: config.CAConstraint{IsCA: true},
  1223. Usage: []string{"signing", "key encipherment", "server auth", "client auth"},
  1224. ExpiryString: "8760h",
  1225. },
  1226. }
  1227. testSigner, err := NewSignerFromFile(testCaFile, testCaKeyFile, config)
  1228. if err != nil {
  1229. t.Fatalf("%v", err)
  1230. }
  1231. // Generate a precert
  1232. k, err := rsa.GenerateKey(rand.Reader, 1024)
  1233. if err != nil {
  1234. t.Fatalf("Failed to generate test key: %s", err)
  1235. }
  1236. _uri, _ := url.Parse("https://www.cloudflare.com")
  1237. precertBytes, err := testSigner.sign(&x509.Certificate{
  1238. SignatureAlgorithm: x509.SHA512WithRSA,
  1239. PublicKey: k.Public(),
  1240. SerialNumber: big.NewInt(10),
  1241. Subject: pkix.Name{CommonName: "CN"},
  1242. NotBefore: time.Now(),
  1243. NotAfter: time.Now().Add(time.Hour),
  1244. ExtraExtensions: []pkix.Extension{
  1245. {Id: signer.CTPoisonOID, Critical: true, Value: []byte{0x05, 0x00}},
  1246. },
  1247. ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
  1248. SubjectKeyId: []byte{0, 1},
  1249. AuthorityKeyId: []byte{1, 0},
  1250. OCSPServer: []string{"ocsp?"},
  1251. IssuingCertificateURL: []string{"url"},
  1252. DNSNames: []string{"example.com"},
  1253. EmailAddresses: []string{"email@example.com"},
  1254. URIs: []*url.URL{_uri},
  1255. IPAddresses: []net.IP{net.ParseIP("1.1.1.1")},
  1256. CRLDistributionPoints: []string{"crl"},
  1257. PolicyIdentifiers: []asn1.ObjectIdentifier{{1, 2, 3}},
  1258. }, 0, nil)
  1259. if err != nil {
  1260. t.Fatalf("Failed to sign request: %s", err)
  1261. }
  1262. block, _ := pem.Decode(precertBytes)
  1263. precert, err := x509.ParseCertificate(block.Bytes)
  1264. if err != nil {
  1265. t.Fatalf("Failed to parse signed cert: %s", err)
  1266. }
  1267. // Create a cert from the precert
  1268. scts := []ct.SignedCertificateTimestamp{{}}
  1269. certBytes, err := testSigner.SignFromPrecert(precert, scts)
  1270. if err != nil {
  1271. t.Fatalf("Failed to sign cert from precert: %s", err)
  1272. }
  1273. block, _ = pem.Decode(certBytes)
  1274. cert, err := x509.ParseCertificate(block.Bytes)
  1275. if err != nil {
  1276. t.Fatalf("Failed to parse signed cert: %s", err)
  1277. }
  1278. // check cert doesn't contains poison extension
  1279. poisoned := false
  1280. for _, ext := range cert.Extensions {
  1281. if ext.Id.Equal(signer.CTPoisonOID) {
  1282. poisoned = true
  1283. break
  1284. }
  1285. }
  1286. if poisoned {
  1287. t.Fatal("Certificate with poison CT extension was returned")
  1288. }
  1289. // check cert contains SCT list extension
  1290. list := false
  1291. for _, ext := range cert.Extensions {
  1292. if ext.Id.Equal(signer.SCTListOID) {
  1293. list = true
  1294. break
  1295. }
  1296. }
  1297. if !list {
  1298. t.Fatal("Certificate without SCT list extension was returned")
  1299. }
  1300. // Break poison extension
  1301. precert.Extensions[7].Value = []byte{1, 3, 3, 7}
  1302. _, err = testSigner.SignFromPrecert(precert, scts)
  1303. if err == nil {
  1304. t.Fatal("SignFromPrecert didn't fail with invalid poison extension")
  1305. }
  1306. precert.Extensions[7].Critical = false
  1307. _, err = testSigner.SignFromPrecert(precert, scts)
  1308. if err == nil {
  1309. t.Fatal("SignFromPrecert didn't fail with non-critical poison extension")
  1310. }
  1311. precert.Extensions = append(precert.Extensions[:7], precert.Extensions[8:]...)
  1312. _, err = testSigner.SignFromPrecert(precert, scts)
  1313. if err == nil {
  1314. t.Fatal("SignFromPrecert didn't fail with missing poison extension")
  1315. }
  1316. precert.Signature = []byte("nop")
  1317. _, err = testSigner.SignFromPrecert(precert, scts)
  1318. if err == nil {
  1319. t.Fatal("SignFromPrecert didn't fail with signature not from CA")
  1320. }
  1321. }
  1322. func TestLint(t *testing.T) {
  1323. k, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  1324. serial := big.NewInt(1337)
  1325. // jankyTemplate is an x509 cert template that mostly passes through zlint
  1326. // without errors/warnings. It is used as the basis of both the signer's issuing
  1327. // certificate and the end entity certificate that is linted.
  1328. jankyTemplate := &x509.Certificate{
  1329. Subject: pkix.Name{
  1330. CommonName: "janky.cert",
  1331. },
  1332. SerialNumber: serial,
  1333. NotBefore: time.Now(),
  1334. NotAfter: time.Now().AddDate(0, 0, 90),
  1335. KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
  1336. ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
  1337. PolicyIdentifiers: []asn1.ObjectIdentifier{
  1338. {1, 2, 3},
  1339. },
  1340. BasicConstraintsValid: true,
  1341. IsCA: true,
  1342. IssuingCertificateURL: []string{"http://ca.cpu"},
  1343. SubjectKeyId: []byte("⚿"),
  1344. PublicKey: k.Public(),
  1345. }
  1346. // Create a self-signed issuer certificate to use as the CA
  1347. issuerDer, _ := x509.CreateCertificate(rand.Reader, jankyTemplate, jankyTemplate, k.Public(), k)
  1348. issuerCert, _ := x509.ParseCertificate(issuerDer)
  1349. lintSigner := &Signer{
  1350. lintPriv: k,
  1351. ca: issuerCert,
  1352. }
  1353. // Reconfigure the template for an end-entity certificate.
  1354. // On purpose this template will trip the following lints:
  1355. // 1. e_sub_cert_aia_does_not_contain_ocsp_url because there is no OCSP URL.
  1356. // 2. e_dnsname_not_valid_tld because `.cert` is not a real TLD
  1357. serial = big.NewInt(1338)
  1358. jankyTemplate.SerialNumber = serial
  1359. jankyTemplate.Subject.CommonName = "www.janky.cert"
  1360. jankyTemplate.DNSNames = []string{"janky.cert", "www.janky.cert"}
  1361. jankyTemplate.KeyUsage = x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment
  1362. jankyTemplate.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}
  1363. jankyTemplate.IsCA = false
  1364. ignoredLintNameRegistry, err := lint.GlobalRegistry().Filter(lint.FilterOptions{
  1365. ExcludeNames: []string{"e_dnsname_not_valid_tld"},
  1366. })
  1367. if err != nil {
  1368. t.Fatalf("failed to construct ignoredLintNamesRegistry: %v", err)
  1369. }
  1370. ignoredLintSourcesRegistry, err := lint.GlobalRegistry().Filter(lint.FilterOptions{
  1371. ExcludeSources: lint.SourceList{lint.CABFBaselineRequirements},
  1372. })
  1373. if err != nil {
  1374. t.Fatalf("failed to construct ignoredLintSourcesRegistry: %v", err)
  1375. }
  1376. testCases := []struct {
  1377. name string
  1378. signer *Signer
  1379. lintErrLevel lint.LintStatus
  1380. lintRegistry lint.Registry
  1381. expectedErr error
  1382. expectedErrResults map[string]lint.LintResult
  1383. }{
  1384. {
  1385. name: "linting disabled",
  1386. signer: lintSigner,
  1387. },
  1388. {
  1389. name: "signer without lint key",
  1390. signer: &Signer{},
  1391. lintErrLevel: lint.NA,
  1392. expectedErr: errors.New(`{"code":2500,"message":"Private key is unavailable"}`),
  1393. },
  1394. {
  1395. name: "lint results above err level",
  1396. signer: lintSigner,
  1397. lintErrLevel: lint.Notice,
  1398. expectedErr: errors.New("pre-issuance linting found 2 error results"),
  1399. expectedErrResults: map[string]lint.LintResult{
  1400. "e_sub_cert_aia_does_not_contain_ocsp_url": lint.LintResult{Status: 6},
  1401. "e_dnsname_not_valid_tld": lint.LintResult{Status: 6},
  1402. },
  1403. },
  1404. {
  1405. name: "lint results below err level",
  1406. signer: lintSigner,
  1407. lintErrLevel: lint.Warn,
  1408. expectedErr: errors.New("pre-issuance linting found 2 error results"),
  1409. expectedErrResults: map[string]lint.LintResult{
  1410. "e_sub_cert_aia_does_not_contain_ocsp_url": lint.LintResult{Status: 6},
  1411. "e_dnsname_not_valid_tld": lint.LintResult{Status: 6},
  1412. },
  1413. },
  1414. {
  1415. name: "ignored lint names, lint results above err level",
  1416. signer: lintSigner,
  1417. lintErrLevel: lint.Notice,
  1418. lintRegistry: ignoredLintNameRegistry,
  1419. expectedErr: errors.New("pre-issuance linting found 1 error results"),
  1420. expectedErrResults: map[string]lint.LintResult{
  1421. "e_sub_cert_aia_does_not_contain_ocsp_url": lint.LintResult{Status: 6},
  1422. },
  1423. },
  1424. {
  1425. name: "ignored lint sources, lint results above err level",
  1426. signer: lintSigner,
  1427. lintErrLevel: lint.Notice,
  1428. lintRegistry: ignoredLintSourcesRegistry,
  1429. },
  1430. }
  1431. for _, tc := range testCases {
  1432. t.Run(tc.name, func(t *testing.T) {
  1433. err := tc.signer.lint(*jankyTemplate, tc.lintErrLevel, tc.lintRegistry)
  1434. if err != nil && tc.expectedErr == nil {
  1435. t.Errorf("Expected no err, got %#v", err)
  1436. } else if err == nil && tc.expectedErr != nil {
  1437. t.Errorf("Expected err %v, got nil", tc.expectedErr)
  1438. } else if err != nil && tc.expectedErr != nil {
  1439. actual := err.Error()
  1440. expected := tc.expectedErr.Error()
  1441. if actual != expected {
  1442. t.Errorf("Expected err %q got %q", expected, actual)
  1443. }
  1444. if len(tc.expectedErrResults) > 0 {
  1445. le, ok := err.(*LintError)
  1446. if !ok {
  1447. t.Fatalf("expected LintError type err, got %v", err)
  1448. }
  1449. if count := len(le.ErrorResults); count != len(tc.expectedErrResults) {
  1450. t.Fatalf("expected %d LintError results, got %d", len(tc.expectedErrResults), len(le.ErrorResults))
  1451. }
  1452. for name, result := range le.ErrorResults {
  1453. if result.Status != tc.expectedErrResults[name].Status {
  1454. t.Errorf("expected error from lint %q to have status %d not %d",
  1455. name, tc.expectedErrResults[name].Status, result.Status)
  1456. }
  1457. if result.Details != tc.expectedErrResults[name].Details {
  1458. t.Errorf("expected error from lint %q to have details %q not %q",
  1459. name, tc.expectedErrResults[name].Details, result.Details)
  1460. }
  1461. }
  1462. }
  1463. }
  1464. })
  1465. }
  1466. }