// New returns a new PKCS #11 signer. func NewPKCS11Signer(cfg ocspConfig.Config) (ocsp.Signer, error) { log.Debugf("Loading PKCS #11 module %s", cfg.PKCS11.Module) certData, err := ioutil.ReadFile(cfg.CACertFile) if err != nil { return nil, errors.New(errors.CertificateError, errors.ReadFailed) } cert, err := helpers.ParseCertificatePEM(certData) if err != nil { return nil, err } PKCS11 := cfg.PKCS11 priv, err := pkcs11key.New(PKCS11.Module, PKCS11.Token, PKCS11.PIN, PKCS11.Label) if err != nil { return nil, errors.New(errors.PrivateKeyError, errors.ReadFailed) } return ocsp.NewSigner(cert, cert, priv, cfg.Interval) }
func initAuthorities(t *testing.T) (core.CertificateAuthority, *DummyValidationAuthority, *sa.SQLStorageAuthority, *RegistrationAuthorityImpl, func()) { err := json.Unmarshal(AccountKeyJSONA, &AccountKeyA) test.AssertNotError(t, err, "Failed to unmarshal public JWK") err = json.Unmarshal(AccountKeyJSONB, &AccountKeyB) test.AssertNotError(t, err, "Failed to unmarshal public JWK") err = json.Unmarshal(AccountKeyJSONC, &AccountKeyC) test.AssertNotError(t, err, "Failed to unmarshal public JWK") err = json.Unmarshal(AccountPrivateKeyJSON, &AccountPrivateKey) test.AssertNotError(t, err, "Failed to unmarshal private JWK") err = json.Unmarshal(ShortKeyJSON, &ShortKey) test.AssertNotError(t, err, "Failed to unmarshall JWK") dbMap, err := sa.NewDbMap(dbConnStr) if err != nil { t.Fatalf("Failed to create dbMap: %s", err) } ssa, err := sa.NewSQLStorageAuthority(dbMap) if err != nil { t.Fatalf("Failed to create SA: %s", err) } err = ssa.CreateTablesIfNotExists() if err != nil { t.Fatalf("Failed to create SA tables: %s", err) } if err = dbMap.TruncateTables(); err != nil { t.Fatalf("Failed to truncate SA tables: %s", err) } va := &DummyValidationAuthority{} // PEM files in certificate-authority_test.go caKeyPEM, _ := pem.Decode([]byte(CAkeyPEM)) caKey, _ := x509.ParsePKCS1PrivateKey(caKeyPEM.Bytes) caCertPEM, _ := pem.Decode([]byte(CAcertPEM)) caCert, _ := x509.ParseCertificate(caCertPEM.Bytes) basicPolicy := &cfsslConfig.Signing{ Default: &cfsslConfig.SigningProfile{ Usage: []string{"server auth", "client auth"}, Expiry: 1 * time.Hour, CSRWhitelist: &cfsslConfig.CSRWhitelist{ PublicKey: true, PublicKeyAlgorithm: true, SignatureAlgorithm: true, DNSNames: true, }, }, } signer, _ := local.NewSigner(caKey, caCert, x509.SHA256WithRSA, basicPolicy) ocspSigner, _ := ocsp.NewSigner(caCert, caCert, caKey, time.Hour) pa := policy.NewPolicyAuthorityImpl() cadb, caDBCleanUp := caDBImpl(t) ca := ca.CertificateAuthorityImpl{ Signer: signer, OCSPSigner: ocspSigner, SA: ssa, PA: pa, DB: cadb, ValidityPeriod: time.Hour * 2190, NotAfter: time.Now().Add(time.Hour * 8761), MaxKeySize: 4096, } cleanUp := func() { if err = dbMap.TruncateTables(); err != nil { t.Fatalf("Failed to truncate tables after the test: %s", err) } dbMap.Db.Close() caDBCleanUp() } csrDER, _ := hex.DecodeString(CSRhex) ExampleCSR, _ = x509.ParseCertificateRequest(csrDER) // This registration implicitly gets ID = 1 Registration, _ = ssa.NewRegistration(core.Registration{Key: AccountKeyA}) ra := NewRegistrationAuthorityImpl() ra.SA = ssa ra.VA = va ra.CA = &ca ra.PA = pa ra.AuthzBase = "http://acme.invalid/authz/" ra.MaxKeySize = 4096 ra.DNSResolver = &mocks.MockDNS{} AuthzInitial.RegistrationID = Registration.ID AuthzUpdated = AuthzInitial AuthzFinal = AuthzUpdated AuthzFinal.Status = "valid" exp := time.Now().Add(365 * 24 * time.Hour) AuthzFinal.Expires = &exp AuthzFinal.Challenges[0].Status = "valid" return &ca, va, ssa, &ra, cleanUp }
// NewCertificateAuthorityImpl creates a CA that talks to a remote CFSSL // instance. (To use a local signer, simply instantiate CertificateAuthorityImpl // directly.) Communications with the CA are authenticated with MACs, // using CFSSL's authenticated signature scheme. A CA created in this way // issues for a single profile on the remote signer, which is indicated // by name in this constructor. func NewCertificateAuthorityImpl(cadb core.CertificateAuthorityDatabase, config cmd.CAConfig, clk clock.Clock, issuerCert string) (*CertificateAuthorityImpl, error) { var ca *CertificateAuthorityImpl var err error logger := blog.GetAuditLogger() logger.Notice("Certificate Authority Starting") if config.SerialPrefix <= 0 || config.SerialPrefix >= 256 { err = errors.New("Must have a positive non-zero serial prefix less than 256 for CA.") return nil, err } // CFSSL requires processing JSON configs through its own LoadConfig, so we // serialize and then deserialize. cfsslJSON, err := json.Marshal(config.CFSSL) if err != nil { return nil, err } cfsslConfigObj, err := cfsslConfig.LoadConfig(cfsslJSON) if err != nil { return nil, err } // Load the private key, which can be a file or a PKCS#11 key. priv, err := loadKey(config.Key) if err != nil { return nil, err } issuer, err := loadIssuer(issuerCert) if err != nil { return nil, err } signer, err := local.NewSigner(priv, issuer, x509.SHA256WithRSA, cfsslConfigObj.Signing) if err != nil { return nil, err } if config.LifespanOCSP == "" { return nil, errors.New("Config must specify an OCSP lifespan period.") } lifespanOCSP, err := time.ParseDuration(config.LifespanOCSP) if err != nil { return nil, err } // Set up our OCSP signer. Note this calls for both the issuer cert and the // OCSP signing cert, which are the same in our case. ocspSigner, err := ocsp.NewSigner(issuer, issuer, priv, lifespanOCSP) if err != nil { return nil, err } ca = &CertificateAuthorityImpl{ Signer: signer, OCSPSigner: ocspSigner, profile: config.Profile, DB: cadb, Prefix: config.SerialPrefix, Clk: clk, log: logger, NotAfter: issuer.NotAfter, } if config.Expiry == "" { return nil, errors.New("Config must specify an expiry period.") } ca.ValidityPeriod, err = time.ParseDuration(config.Expiry) if err != nil { return nil, err } ca.MaxNames = config.MaxNames return ca, nil }
// NewCertificateAuthorityImpl creates a CA that talks to a remote CFSSL // instance. (To use a local signer, simply instantiate CertificateAuthorityImpl // directly.) Communications with the CA are authenticated with MACs, // using CFSSL's authenticated signature scheme. A CA created in this way // issues for a single profile on the remote signer, which is indicated // by name in this constructor. func NewCertificateAuthorityImpl( config cmd.CAConfig, clk clock.Clock, stats statsd.Statter, issuer *x509.Certificate, privateKey crypto.Signer, keyPolicy core.KeyPolicy, ) (*CertificateAuthorityImpl, error) { var ca *CertificateAuthorityImpl var err error logger := blog.GetAuditLogger() logger.Notice("Certificate Authority Starting") if config.SerialPrefix <= 0 || config.SerialPrefix >= 256 { err = errors.New("Must have a positive non-zero serial prefix less than 256 for CA.") return nil, err } // CFSSL requires processing JSON configs through its own LoadConfig, so we // serialize and then deserialize. cfsslJSON, err := json.Marshal(config.CFSSL) if err != nil { return nil, err } cfsslConfigObj, err := cfsslConfig.LoadConfig(cfsslJSON) if err != nil { return nil, err } signer, err := local.NewSigner(privateKey, issuer, x509.SHA256WithRSA, cfsslConfigObj.Signing) if err != nil { return nil, err } if config.LifespanOCSP == "" { return nil, errors.New("Config must specify an OCSP lifespan period.") } lifespanOCSP, err := time.ParseDuration(config.LifespanOCSP) if err != nil { return nil, err } // Set up our OCSP signer. Note this calls for both the issuer cert and the // OCSP signing cert, which are the same in our case. ocspSigner, err := ocsp.NewSigner(issuer, issuer, privateKey, lifespanOCSP) if err != nil { return nil, err } rsaProfile := config.RSAProfile ecdsaProfile := config.ECDSAProfile if config.Profile != "" { if rsaProfile != "" || ecdsaProfile != "" { return nil, errors.New("either specify profile or rsaProfile and ecdsaProfile, but not both") } rsaProfile = config.Profile ecdsaProfile = config.Profile } if rsaProfile == "" || ecdsaProfile == "" { return nil, errors.New("must specify rsaProfile and ecdsaProfile") } ca = &CertificateAuthorityImpl{ signer: signer, ocspSigner: ocspSigner, rsaProfile: rsaProfile, ecdsaProfile: ecdsaProfile, prefix: config.SerialPrefix, clk: clk, log: logger, stats: stats, notAfter: issuer.NotAfter, hsmFaultTimeout: config.HSMFaultTimeout.Duration, keyPolicy: keyPolicy, } if config.Expiry == "" { return nil, errors.New("Config must specify an expiry period.") } ca.validityPeriod, err = time.ParseDuration(config.Expiry) if err != nil { return nil, err } ca.maxNames = config.MaxNames return ca, nil }
func initAuthorities(t *testing.T) (*DummyValidationAuthority, *sa.SQLStorageAuthority, *RegistrationAuthorityImpl, clock.FakeClock, func()) { err := json.Unmarshal(AccountKeyJSONA, &AccountKeyA) test.AssertNotError(t, err, "Failed to unmarshal public JWK") err = json.Unmarshal(AccountKeyJSONB, &AccountKeyB) test.AssertNotError(t, err, "Failed to unmarshal public JWK") err = json.Unmarshal(AccountKeyJSONC, &AccountKeyC) test.AssertNotError(t, err, "Failed to unmarshal public JWK") err = json.Unmarshal(AccountPrivateKeyJSON, &AccountPrivateKey) test.AssertNotError(t, err, "Failed to unmarshal private JWK") err = json.Unmarshal(ShortKeyJSON, &ShortKey) test.AssertNotError(t, err, "Failed to unmarshal JWK") fc := clock.NewFake() dbMap, err := sa.NewDbMap(vars.DBConnSA) if err != nil { t.Fatalf("Failed to create dbMap: %s", err) } ssa, err := sa.NewSQLStorageAuthority(dbMap, fc) if err != nil { t.Fatalf("Failed to create SA: %s", err) } saDBCleanUp := test.ResetSATestDatabase(t) va := &DummyValidationAuthority{} // PEM files in certificate-authority_test.go caKeyPEM, _ := pem.Decode([]byte(CAkeyPEM)) caKey, _ := x509.ParsePKCS1PrivateKey(caKeyPEM.Bytes) caCertPEM, _ := pem.Decode([]byte(CAcertPEM)) caCert, _ := x509.ParseCertificate(caCertPEM.Bytes) basicPolicy := &cfsslConfig.Signing{ Default: &cfsslConfig.SigningProfile{ Usage: []string{"server auth", "client auth"}, Expiry: 1 * time.Hour, CSRWhitelist: &cfsslConfig.CSRWhitelist{ PublicKey: true, PublicKeyAlgorithm: true, SignatureAlgorithm: true, DNSNames: true, }, }, } signer, _ := local.NewSigner(caKey, caCert, x509.SHA256WithRSA, basicPolicy) ocspSigner, _ := ocsp.NewSigner(caCert, caCert, caKey, time.Hour) paDbMap, err := sa.NewDbMap(vars.DBConnPolicy) if err != nil { t.Fatalf("Failed to create dbMap: %s", err) } policyDBCleanUp := test.ResetPolicyTestDatabase(t) pa, err := policy.NewPolicyAuthorityImpl(paDbMap, false, SupportedChallenges) test.AssertNotError(t, err, "Couldn't create PA") ca := ca.CertificateAuthorityImpl{ Signer: signer, OCSPSigner: ocspSigner, SA: ssa, PA: pa, ValidityPeriod: time.Hour * 2190, NotAfter: time.Now().Add(time.Hour * 8761), Clk: fc, Publisher: &mocks.Publisher{}, } cleanUp := func() { saDBCleanUp() policyDBCleanUp() } csrDER, _ := hex.DecodeString(CSRhex) ExampleCSR, _ = x509.ParseCertificateRequest(csrDER) Registration, _ = ssa.NewRegistration(core.Registration{ Key: AccountKeyA, InitialIP: net.ParseIP("3.2.3.3"), }) stats, _ := statsd.NewNoopClient() ra := NewRegistrationAuthorityImpl(fc, blog.GetAuditLogger(), stats, &DomainCheck{va}, cmd.RateLimitConfig{ TotalCertificates: cmd.RateLimitPolicy{ Threshold: 100, Window: cmd.ConfigDuration{Duration: 24 * 90 * time.Hour}, }, }, 1) ra.SA = ssa ra.VA = va ra.CA = &ca ra.PA = pa ra.DNSResolver = &mocks.DNSResolver{} AuthzInitial.RegistrationID = Registration.ID challenges, combinations, err := pa.ChallengesFor(AuthzInitial.Identifier, &Registration.Key) AuthzInitial.Challenges = challenges AuthzInitial.Combinations = combinations AuthzFinal = AuthzInitial AuthzFinal.Status = "valid" exp := time.Now().Add(365 * 24 * time.Hour) AuthzFinal.Expires = &exp AuthzFinal.Challenges[0].Status = "valid" return va, ssa, ra, fc, cleanUp }
// NewCertificateAuthorityImpl creates a CA that talks to a remote CFSSL // instance. (To use a local signer, simply instantiate CertificateAuthorityImpl // directly.) Communications with the CA are authenticated with MACs, // using CFSSL's authenticated signature scheme. A CA created in this way // issues for a single profile on the remote signer, which is indicated // by name in this constructor. func NewCertificateAuthorityImpl(cadb core.CertificateAuthorityDatabase, config Config) (*CertificateAuthorityImpl, error) { var ca *CertificateAuthorityImpl var err error logger := blog.GetAuditLogger() logger.Notice("Certificate Authority Starting") if config.SerialPrefix <= 0 || config.SerialPrefix >= 256 { err = errors.New("Must have a positive non-zero serial prefix less than 256 for CA.") return nil, err } // Create the remote signer localProfile := cfsslConfig.SigningProfile{ Expiry: time.Hour, // BOGUS: Required by CFSSL, but not used RemoteName: config.Server, // BOGUS: Only used as a flag by CFSSL RemoteServer: config.Server, UseSerialSeq: true, } localProfile.Provider, err = auth.New(config.AuthKey, nil) if err != nil { return nil, err } signer, err := remote.NewSigner(&cfsslConfig.Signing{Default: &localProfile}) if err != nil { return nil, err } issuer, err := loadIssuer(config.IssuerCert) if err != nil { return nil, err } // In test mode, load a private key from a file. // TODO: This should rely on the CFSSL config, to make it easy to use a key // from a file vs an HSM. https://github.com/letsencrypt/boulder/issues/163 issuerKey, err := loadIssuerKey(config.IssuerKey) if err != nil { return nil, err } // Set up our OCSP signer. Note this calls for both the issuer cert and the // OCSP signing cert, which are the same in our case. ocspSigner, err := ocsp.NewSigner(issuer, issuer, issuerKey, time.Hour*24*4) if err != nil { return nil, err } pa := policy.NewPolicyAuthorityImpl() ca = &CertificateAuthorityImpl{ Signer: signer, OCSPSigner: ocspSigner, profile: config.Profile, PA: pa, DB: cadb, Prefix: config.SerialPrefix, log: logger, NotAfter: issuer.NotAfter, } ca.ValidityPeriod, err = time.ParseDuration(config.Expiry) if err != nil { return nil, err } return ca, nil }
func initAuthorities(t *testing.T) (*DummyValidationAuthority, *sa.SQLStorageAuthority, *RegistrationAuthorityImpl, clock.FakeClock, func()) { err := json.Unmarshal(AccountKeyJSONA, &AccountKeyA) test.AssertNotError(t, err, "Failed to unmarshal public JWK") err = json.Unmarshal(AccountKeyJSONB, &AccountKeyB) test.AssertNotError(t, err, "Failed to unmarshal public JWK") err = json.Unmarshal(AccountKeyJSONC, &AccountKeyC) test.AssertNotError(t, err, "Failed to unmarshal public JWK") err = json.Unmarshal(AccountPrivateKeyJSON, &AccountPrivateKey) test.AssertNotError(t, err, "Failed to unmarshal private JWK") err = json.Unmarshal(ShortKeyJSON, &ShortKey) test.AssertNotError(t, err, "Failed to unmarshall JWK") fc := clock.NewFake() dbMap, err := sa.NewDbMap(saDBConnStr) if err != nil { t.Fatalf("Failed to create dbMap: %s", err) } ssa, err := sa.NewSQLStorageAuthority(dbMap, fc) if err != nil { t.Fatalf("Failed to create SA: %s", err) } saDBCleanUp := test.ResetTestDatabase(t, dbMap.Db) va := &DummyValidationAuthority{} // PEM files in certificate-authority_test.go caKeyPEM, _ := pem.Decode([]byte(CAkeyPEM)) caKey, _ := x509.ParsePKCS1PrivateKey(caKeyPEM.Bytes) caCertPEM, _ := pem.Decode([]byte(CAcertPEM)) caCert, _ := x509.ParseCertificate(caCertPEM.Bytes) basicPolicy := &cfsslConfig.Signing{ Default: &cfsslConfig.SigningProfile{ Usage: []string{"server auth", "client auth"}, Expiry: 1 * time.Hour, CSRWhitelist: &cfsslConfig.CSRWhitelist{ PublicKey: true, PublicKeyAlgorithm: true, SignatureAlgorithm: true, DNSNames: true, }, }, } signer, _ := local.NewSigner(caKey, caCert, x509.SHA256WithRSA, basicPolicy) ocspSigner, _ := ocsp.NewSigner(caCert, caCert, caKey, time.Hour) paDbMap, err := sa.NewDbMap(paDBConnStr) if err != nil { t.Fatalf("Failed to create dbMap: %s", err) } policyDBCleanUp := test.ResetTestDatabase(t, paDbMap.Db) pa, err := policy.NewPolicyAuthorityImpl(paDbMap, false) test.AssertNotError(t, err, "Couldn't create PA") cadb, caDBCleanUp := caDBImpl(t) ca := ca.CertificateAuthorityImpl{ Signer: signer, OCSPSigner: ocspSigner, SA: ssa, PA: pa, DB: cadb, ValidityPeriod: time.Hour * 2190, NotAfter: time.Now().Add(time.Hour * 8761), Clk: fc, } cleanUp := func() { saDBCleanUp() caDBCleanUp() policyDBCleanUp() } csrDER, _ := hex.DecodeString(CSRhex) ExampleCSR, _ = x509.ParseCertificateRequest(csrDER) Registration, _ = ssa.NewRegistration(core.Registration{Key: AccountKeyA}) ra := NewRegistrationAuthorityImpl(fc, blog.GetAuditLogger()) ra.SA = ssa ra.VA = va ra.CA = &ca ra.PA = pa ra.DNSResolver = &mocks.MockDNS{} AuthzInitial.RegistrationID = Registration.ID AuthzUpdated = AuthzInitial AuthzFinal = AuthzUpdated AuthzFinal.Status = "valid" exp := time.Now().Add(365 * 24 * time.Hour) AuthzFinal.Expires = &exp AuthzFinal.Challenges[0].Status = "valid" return va, ssa, &ra, fc, cleanUp }
func initAuthorities(t *testing.T) (core.CertificateAuthority, *DummyValidationAuthority, *sa.SQLStorageAuthority, core.RegistrationAuthority) { err := json.Unmarshal(AccountKeyJSONA, &AccountKeyA) test.AssertNotError(t, err, "Failed to unmarshal public JWK") err = json.Unmarshal(AccountKeyJSONB, &AccountKeyB) test.AssertNotError(t, err, "Failed to unmarshal public JWK") err = json.Unmarshal(AccountKeyJSONC, &AccountKeyC) test.AssertNotError(t, err, "Failed to unmarshal public JWK") err = json.Unmarshal(AccountPrivateKeyJSON, &AccountPrivateKey) test.AssertNotError(t, err, "Failed to unmarshal private JWK") err = json.Unmarshal(ShortKeyJSON, &ShortKey) test.AssertNotError(t, err, "Failed to unmarshall JWK") sa, err := sa.NewSQLStorageAuthority("sqlite3", ":memory:") test.AssertNotError(t, err, "Failed to create SA") sa.CreateTablesIfNotExists() va := &DummyValidationAuthority{} // PEM files in certificate-authority_test.go caKeyPEM, _ := pem.Decode([]byte(CAkeyPEM)) caKey, _ := x509.ParsePKCS1PrivateKey(caKeyPEM.Bytes) caCertPEM, _ := pem.Decode([]byte(CAcertPEM)) caCert, _ := x509.ParseCertificate(caCertPEM.Bytes) basicPolicy := &cfsslConfig.Signing{ Default: &cfsslConfig.SigningProfile{ Usage: []string{"server auth", "client auth"}, Expiry: 1 * time.Hour, CSRWhitelist: &cfsslConfig.CSRWhitelist{ PublicKey: true, PublicKeyAlgorithm: true, SignatureAlgorithm: true, DNSNames: true, }, }, } signer, _ := local.NewSigner(caKey, caCert, x509.SHA256WithRSA, basicPolicy) ocspSigner, _ := ocsp.NewSigner(caCert, caCert, caKey, time.Hour) pa := policy.NewPolicyAuthorityImpl() cadb, _ := test.NewMockCertificateAuthorityDatabase() ca := ca.CertificateAuthorityImpl{ Signer: signer, OCSPSigner: ocspSigner, SA: sa, PA: pa, DB: cadb, ValidityPeriod: time.Hour * 2190, NotAfter: time.Now().Add(time.Hour * 8761), MaxKeySize: 4096, } csrDER, _ := hex.DecodeString(CSRhex) ExampleCSR, _ = x509.ParseCertificateRequest(csrDER) // This registration implicitly gets ID = 1 Registration, _ = sa.NewRegistration(core.Registration{Key: AccountKeyA}) ra := NewRegistrationAuthorityImpl() ra.SA = sa ra.VA = va ra.CA = &ca ra.PA = pa ra.AuthzBase = "http://acme.invalid/authz/" ra.MaxKeySize = 4096 AuthzInitial.RegistrationID = Registration.ID AuthzUpdated = AuthzInitial AuthzUpdated.Challenges[0].Path = "Hf5GrX4Q7EBax9hc2jJnfw" AuthzFinal = AuthzUpdated AuthzFinal.Status = "valid" exp := time.Now().Add(365 * 24 * time.Hour) AuthzFinal.Expires = &exp AuthzFinal.Challenges[0].Status = "valid" return &ca, va, sa, &ra }