77 "crypto/ecdsa"
88 "crypto/rand"
99 "crypto/rsa"
10+ "crypto/sha256"
1011 "crypto/x509"
1112 "encoding/asn1"
1213 "encoding/hex"
@@ -36,8 +37,8 @@ import (
3637 corepb "github.com/letsencrypt/boulder/core/proto"
3738 csrlib "github.com/letsencrypt/boulder/csr"
3839 berrors "github.com/letsencrypt/boulder/errors"
40+ "github.com/letsencrypt/boulder/features"
3941 "github.com/letsencrypt/boulder/goodkey"
40- "github.com/letsencrypt/boulder/issuercerts"
4142 blog "github.com/letsencrypt/boulder/log"
4243 sapb "github.com/letsencrypt/boulder/sa/proto"
4344)
@@ -115,9 +116,11 @@ const (
115116type CertificateAuthorityImpl struct {
116117 rsaProfile string
117118 ecdsaProfile string
119+ // A map from issuer cert common name to an internalIssuer struct
120+ issuers map [string ]* internalIssuer
118121 // A map from issuer ID to internalIssuer
119- idToIssuer map [issuercerts. ID ]* internalIssuer
120- // The issuer that will be used for issuance (as opposed to OCSP signing)
122+ idToIssuer map [int64 ]* internalIssuer
123+ // The common name of the default issuer cert
121124 defaultIssuer * internalIssuer
122125 sa certificateStorage
123126 pa core.PolicyAuthority
@@ -163,12 +166,11 @@ func makeInternalIssuers(
163166 issuers []Issuer ,
164167 policy * cfsslConfig.Signing ,
165168 lifespanOCSP time.Duration ,
166- ) (map [issuercerts. ID ]* internalIssuer , error ) {
169+ ) (map [string ]* internalIssuer , error ) {
167170 if len (issuers ) == 0 {
168171 return nil , errors .New ("No issuers specified." )
169172 }
170- internalIssuers := make (map [issuercerts.ID ]* internalIssuer )
171- cns := make (map [string ]bool )
173+ internalIssuers := make (map [string ]* internalIssuer )
172174 for _ , iss := range issuers {
173175 if iss .Cert == nil || iss .Signer == nil {
174176 return nil , errors .New ("Issuer with nil cert or signer specified." )
@@ -179,11 +181,10 @@ func makeInternalIssuers(
179181 }
180182
181183 cn := iss .Cert .Subject .CommonName
182- if cns [cn ] {
184+ if internalIssuers [cn ] != nil {
183185 return nil , errors .New ("Multiple issuer certs with the same CommonName are not supported" )
184186 }
185- id := issuercerts .FromCert (iss .Cert ).ID ()
186- internalIssuers [id ] = & internalIssuer {
187+ internalIssuers [cn ] = & internalIssuer {
187188 cert : iss .Cert ,
188189 eeSigner : eeSigner ,
189190 ocspSigner : iss .Signer ,
@@ -192,8 +193,16 @@ func makeInternalIssuers(
192193 return internalIssuers , nil
193194}
194195
196+ // idForIssuer generates a stable ID for an issuer certificate. This
197+ // is used for identifying which issuer issued a certificate in the
198+ // certificateStatus table.
199+ func idForIssuer (cert * x509.Certificate ) int64 {
200+ h := sha256 .Sum256 (cert .Raw )
201+ return big .NewInt (0 ).SetBytes (h [:4 ]).Int64 ()
202+ }
203+
195204// NewCertificateAuthorityImpl creates a CA instance that can sign certificates
196- // from a single issuer (the first in the issuers slice), and can sign OCSP
205+ // from a single issuer (the first first in the issuers slice), and can sign OCSP
197206// for any of the issuer certificates provided.
198207func NewCertificateAuthorityImpl (
199208 config ca_config.CAConfig ,
@@ -242,7 +251,7 @@ func NewCertificateAuthorityImpl(
242251 if err != nil {
243252 return nil , err
244253 }
245- defaultIssuer := internalIssuers [issuercerts . FromCert ( issuers [0 ].Cert ). ID () ]
254+ defaultIssuer := internalIssuers [issuers [0 ].Cert . Subject . CommonName ]
246255
247256 rsaProfile := config .RSAProfile
248257 ecdsaProfile := config .ECDSAProfile
@@ -292,6 +301,7 @@ func NewCertificateAuthorityImpl(
292301 ca = & CertificateAuthorityImpl {
293302 sa : sa ,
294303 pa : pa ,
304+ issuers : internalIssuers ,
295305 defaultIssuer : defaultIssuer ,
296306 rsaProfile : rsaProfile ,
297307 ecdsaProfile : ecdsaProfile ,
@@ -309,9 +319,9 @@ func NewCertificateAuthorityImpl(
309319 signErrorCounter : signErrorCounter ,
310320 }
311321
312- ca .idToIssuer = make (map [issuercerts. ID ]* internalIssuer )
313- for _ , ii := range internalIssuers {
314- id := issuercerts . FromCert (ii .cert ). ID ( )
322+ ca .idToIssuer = make (map [int64 ]* internalIssuer )
323+ for _ , ii := range ca . issuers {
324+ id := idForIssuer (ii .cert )
315325 ca .idToIssuer [id ] = ii
316326 }
317327
@@ -423,33 +433,48 @@ var ocspStatusToCode = map[string]int{
423433func (ca * CertificateAuthorityImpl ) GenerateOCSP (ctx context.Context , req * caPB.GenerateOCSPRequest ) (* caPB.OCSPResponse , error ) {
424434 var issuer * internalIssuer
425435 var serial * big.Int
426- if req .IssuerID == nil {
427- return nil , fmt .Errorf ("no issuerID provided" )
428- }
429- if req .Serial == nil {
430- return nil , fmt .Errorf ("no serial provided" )
431- }
432436 // Once the feature is enabled we need to support both RPCs that include
433437 // IssuerID and those that don't as we still need to be able to update rows
434438 // that didn't have an IssuerID set when they were created. Once this feature
435439 // has been enabled for a full OCSP lifetime cycle we can remove this
436440 // functionality.
437- serialInt , err := core .StringToSerial (* req .Serial )
438- if err != nil {
439- return nil , err
440- }
441- serial = serialInt
442- var ok bool
443- issuer , ok = ca .idToIssuer [issuercerts .ID (* req .IssuerID )]
444- if ! ok {
445- return nil , fmt .Errorf ("This CA doesn't have an issuer cert with ID %d" , * req .IssuerID )
446- }
447- exists , err := ca .sa .SerialExists (ctx , & sapb.Serial {Serial : req .Serial })
448- if err != nil {
449- return nil , err
450- }
451- if ! * exists .Exists {
452- return nil , fmt .Errorf ("GenerateOCSP was asked to sign OCSP for certification with unknown serial %q" , * req .Serial )
441+ if features .Enabled (features .StoreIssuerInfo ) && req .IssuerID != nil {
442+ serialInt , err := core .StringToSerial (* req .Serial )
443+ if err != nil {
444+ return nil , err
445+ }
446+ serial = serialInt
447+ var ok bool
448+ issuer , ok = ca .idToIssuer [* req .IssuerID ]
449+ if ! ok {
450+ return nil , fmt .Errorf ("This CA doesn't have an issuer cert with ID %d" , * req .IssuerID )
451+ }
452+ exists , err := ca .sa .SerialExists (ctx , & sapb.Serial {Serial : req .Serial })
453+ if err != nil {
454+ return nil , err
455+ }
456+ if ! * exists .Exists {
457+ return nil , fmt .Errorf ("GenerateOCSP was asked to sign OCSP for certification with unknown serial %q" , * req .Serial )
458+ }
459+ } else {
460+ cert , err := x509 .ParseCertificate (req .CertDER )
461+ if err != nil {
462+ ca .log .AuditErr (err .Error ())
463+ return nil , err
464+ }
465+
466+ serial = cert .SerialNumber
467+ cn := cert .Issuer .CommonName
468+ issuer = ca .issuers [cn ]
469+ if issuer == nil {
470+ return nil , fmt .Errorf ("This CA doesn't have an issuer cert with CommonName %q" , cn )
471+ }
472+ err = cert .CheckSignatureFrom (issuer .cert )
473+ if err != nil {
474+ return nil , fmt .Errorf ("GenerateOCSP was asked to sign OCSP for cert " +
475+ "%s from %q, but the cert's signature was not valid: %s." ,
476+ core .SerialToString (cert .SerialNumber ), cn , err )
477+ }
453478 }
454479
455480 now := ca .clk .Now ().Truncate (time .Hour )
@@ -498,16 +523,10 @@ func (ca *CertificateAuthorityImpl) IssuePrecertificate(ctx context.Context, iss
498523 return nil , err
499524 }
500525
501- // we currently only use one issuer, in the future when we support multiple
502- // the issuer will need to be derived from issueReq
503- issuerID := int64 (issuercerts .FromCert (ca .defaultIssuer .cert ).ID ())
504-
505526 status := string (core .OCSPStatusGood )
506527 ocspResp , err := ca .GenerateOCSP (ctx , & caPB.GenerateOCSPRequest {
507- Serial : & serialHex ,
508- CertDER : precertDER ,
509- Status : & status ,
510- IssuerID : & issuerID ,
528+ CertDER : precertDER ,
529+ Status : & status ,
511530 })
512531 if err != nil {
513532 err = berrors .InternalServerError (err .Error ())
@@ -516,13 +535,17 @@ func (ca *CertificateAuthorityImpl) IssuePrecertificate(ctx context.Context, iss
516535 }
517536
518537 req := & sapb.AddCertificateRequest {
519- Der : precertDER ,
520- RegID : & regID ,
521- Ocsp : ocspResp .Response ,
522- Issued : & nowNanos ,
523- IssuerID : & issuerID ,
538+ Der : precertDER ,
539+ RegID : & regID ,
540+ Ocsp : ocspResp .Response ,
541+ Issued : & nowNanos ,
524542 }
525543
544+ // we currently only use one issuer, in the future when we support multiple
545+ // the issuer will need to be derived from issueReq
546+ issuerID := idForIssuer (ca .defaultIssuer .cert )
547+ req .IssuerID = & issuerID
548+
526549 _ , err = ca .sa .AddPrecertificate (ctx , req )
527550 if err != nil {
528551 ca .orphanCount .With (prometheus.Labels {"type" : "precert" }).Inc ()
0 commit comments