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