diff --git a/ca/ca_test.go b/ca/ca_test.go index bcd9cde8674..4f853c51676 100644 --- a/ca/ca_test.go +++ b/ca/ca_test.go @@ -1016,13 +1016,8 @@ func TestVerifyTBSCertIsDeterministic(t *testing.T) { errorSubstr: "mismatch between", }, { - // Take this with a grain of salt since this test is not actually - // creating a linting certificate and performing two - // x509.CreateCertificate() calls like - // ca.IssueCertificateForPrecertificate and - // ca.issuePrecertificateInner do. However, we're still going to - // verify the equality. - name: "Valid", + // If the inputs are identical, return success. + name: "identical inputs succeed", lintCertBytes: certDer1, leafCertBytes: certDer1, }, diff --git a/docs/ISSUANCE-CYCLE.md b/docs/ISSUANCE-CYCLE.md index 1dab719aeef..a65afb8ab17 100644 --- a/docs/ISSUANCE-CYCLE.md +++ b/docs/ISSUANCE-CYCLE.md @@ -7,12 +7,12 @@ At a high level: 1. Check that all authorizations are good. 2. Recheck CAA for hostnames that need it. 3. Allocate and store a serial number. -4. Select a certificate profile. -5. Generate and store linting precertificate. -6. Sign, log (and don't store) precertificate. -7. Submit precertificate to CT. -8. Generate linting final certificate. Not logged or stored. -9. Sign, log, and store final certificate. +4. Generate and store linting precertificate. +5. Sign, log (and don't store) precertificate. +6. Submit precertificate to CT. +7. Generate linting final certificate. Not logged or stored. +8. Sign, log, and store final certificate. +9. Submit final certificate to CT. Revocation can happen at any time after (5), whether or not step (6) was successful. We do things this way so that even in the event of a power failure or error storing data, we have a record of what we planned to sign (the tbsCertificate bytes of the linting certificate). diff --git a/ra/ra.go b/ra/ra.go index 6daa0550657..ca446528759 100644 --- a/ra/ra.go +++ b/ra/ra.go @@ -1098,16 +1098,6 @@ func (ra *RegistrationAuthorityImpl) validateFinalizeRequest( return csr, authzs, nil } -func (ra *RegistrationAuthorityImpl) GetSCTs(ctx context.Context, sctRequest *rapb.SCTRequest) (*rapb.SCTResponse, error) { - scts, err := ra.getSCTs(ctx, sctRequest.PrecertDER) - if err != nil { - return nil, err - } - return &rapb.SCTResponse{ - SctDER: scts, - }, nil -} - // issueCertificateOuter exists solely to ensure that all calls to // issueCertificateInner have their result handled uniformly, no matter what // return path that inner function takes. It takes ownership of the logEvent, @@ -1215,23 +1205,8 @@ func (ra *RegistrationAuthorityImpl) countCertificateIssued(ctx context.Context, } } -// issueCertificateInner is part of the [issuance cycle]. -// -// It gets a precertificate from the CA, submits it to CT logs to get SCTs, -// then sends the precertificate and the SCTs to the CA to get a final certificate. -// -// This function is responsible for ensuring that we never try to issue a final -// certificate twice for the same precertificate, because that has the potential -// to create certificates with duplicate serials. For instance, this could -// happen if final certificates were created with different sets of SCTs. This -// function accomplishes that by bailing on issuance if there is any error in -// IssueCertificateForPrecertificate; there are no retries, and serials are -// generated in IssuePrecertificate, so serials with errors are dropped and -// never have final certificates issued for them (because there is a possibility -// that the certificate was actually issued but there was an error returning -// it). -// -// [issuance cycle]: https://github.com/letsencrypt/boulder/blob/main/docs/ISSUANCE-CYCLE.md +// issueCertificateInner rechecks CAA, gets a certificate from the CA, +// and finalizes the order with the certificate serial. func (ra *RegistrationAuthorityImpl) issueCertificateInner( ctx context.Context, csr *x509.CertificateRequest, @@ -1299,14 +1274,14 @@ func (ra *RegistrationAuthorityImpl) issueCertificateInner( return parsedCertificate, nil } -func (ra *RegistrationAuthorityImpl) getSCTs(ctx context.Context, precertDER []byte) (core.SCTDERs, error) { +func (ra *RegistrationAuthorityImpl) GetSCTs(ctx context.Context, sctRequest *rapb.SCTRequest) (*rapb.SCTResponse, error) { started := ra.clk.Now() - precert, err := x509.ParseCertificate(precertDER) + precert, err := x509.ParseCertificate(sctRequest.PrecertDER) if err != nil { return nil, fmt.Errorf("parsing precertificate: %w", err) } - scts, err := ra.ctpolicy.GetSCTs(ctx, precertDER, precert.NotAfter) + scts, err := ra.ctpolicy.GetSCTs(ctx, precert.Raw, precert.NotAfter) took := ra.clk.Since(started) if err != nil { state := "failure" @@ -1321,7 +1296,9 @@ func (ra *RegistrationAuthorityImpl) getSCTs(ctx context.Context, precertDER []b return nil, err } ra.ctpolicyResults.With(prometheus.Labels{"result": "success"}).Observe(took.Seconds()) - return scts, nil + return &rapb.SCTResponse{ + SctDER: scts, + }, nil } // UpdateRegistrationKey updates an existing Registration's key.