From e2e9bf5494c3f144710b412c2864284bc9533d15 Mon Sep 17 00:00:00 2001 From: Herman Slatman Date: Fri, 4 Aug 2023 01:55:52 +0200 Subject: [PATCH] Clarify some SCEP properties --- authority/authority.go | 1 + authority/provisioner/scep.go | 5 +++- scep/authority.go | 50 ++++++++++++++++++----------------- scep/options.go | 2 ++ 4 files changed, 33 insertions(+), 25 deletions(-) diff --git a/authority/authority.go b/authority/authority.go index e6044e4d..f9c58ba6 100644 --- a/authority/authority.go +++ b/authority/authority.go @@ -702,6 +702,7 @@ func (a *Authority) init() error { // only pass the decrypter down when it was successfully created, // meaning it's an RSA key, and `CreateDecrypter` did not fail. options.Decrypter = decrypter + options.DecrypterCert = options.Intermediates[0] } } diff --git a/authority/provisioner/scep.go b/authority/provisioner/scep.go index 626d26ab..396df8e4 100644 --- a/authority/provisioner/scep.go +++ b/authority/provisioner/scep.go @@ -57,6 +57,7 @@ type SCEP struct { decrypter crypto.Decrypter decrypterCertificate *x509.Certificate signer crypto.Signer + signerCertificate *x509.Certificate } // GetID returns the provisioner unique identifier. @@ -246,6 +247,8 @@ func (s *SCEP) Init(config Config) (err error) { if s.decrypterCertificate, err = x509.ParseCertificate(block.Bytes); err != nil { return fmt.Errorf("failed parsing decrypter certificate: %w", err) } + // the decrypter certificate is also the signer certificate + s.signerCertificate = s.decrypterCertificate } // TODO(hs): alternatively, check if the KMS keyManager is a CertificateManager @@ -361,5 +364,5 @@ func (s *SCEP) GetDecrypter() (*x509.Certificate, crypto.Decrypter) { // of a crypto.Signer and a certificate for the public key // corresponding to the private key. func (s *SCEP) GetSigner() (*x509.Certificate, crypto.Signer) { - return s.decrypterCertificate, s.signer + return s.signerCertificate, s.signer } diff --git a/scep/authority.go b/scep/authority.go index c839ab99..d4ca37f2 100644 --- a/scep/authority.go +++ b/scep/authority.go @@ -22,9 +22,10 @@ type Authority struct { signAuth SignAuthority roots []*x509.Certificate intermediates []*x509.Certificate - signerCertificate *x509.Certificate defaultSigner crypto.Signer + signerCertificate *x509.Certificate defaultDecrypter crypto.Decrypter + decrypterCertificate *x509.Certificate scepProvisionerNames []string mu sync.RWMutex @@ -64,16 +65,17 @@ func New(signAuth SignAuthority, opts Options) (*Authority, error) { if err := opts.Validate(); err != nil { return nil, err } - authority := &Authority{ + + return &Authority{ signAuth: signAuth, // TODO: provide signAuth through context instead? roots: opts.Roots, intermediates: opts.Intermediates, - signerCertificate: opts.SignerCert, defaultSigner: opts.Signer, + signerCertificate: opts.SignerCert, defaultDecrypter: opts.Decrypter, + decrypterCertificate: opts.SignerCert, // the intermediate signer cert is also the decrypter cert (if RSA) scepProvisionerNames: opts.SCEPProvisionerNames, - } - return authority, nil + }, nil } // Validate validates if the SCEP Authority has a valid configuration. @@ -181,12 +183,12 @@ func (a *Authority) DecryptPKIEnvelope(ctx context.Context, msg *PKIMessage) err return fmt.Errorf("error parsing pkcs7 content: %w", err) } - cert, pkey, err := a.selectDecrypter(ctx) + cert, decrypter, err := a.selectDecrypter(ctx) if err != nil { return fmt.Errorf("failed selecting decrypter: %w", err) } - envelope, err := p7c.Decrypt(cert, pkey) + envelope, err := p7c.Decrypt(cert, decrypter) if err != nil { return fmt.Errorf("error decrypting encrypted pkcs7 content: %w", err) } @@ -209,7 +211,7 @@ func (a *Authority) DecryptPKIEnvelope(ctx context.Context, msg *PKIMessage) err if err := csr.CheckSignature(); err != nil { return fmt.Errorf("invalid CSR signature; %w", err) } - // check for challengePassword + // extract the challenge password cp, err := microx509util.ParseChallengePassword(msg.pkiEnvelope) if err != nil { return fmt.Errorf("parse challenge password in pkiEnvelope: %w", err) @@ -484,46 +486,46 @@ func (a *Authority) ValidateChallenge(ctx context.Context, challenge, transactio return p.ValidateChallenge(ctx, challenge, transactionID) } -func (a *Authority) selectDecrypter(ctx context.Context) (cert *x509.Certificate, pkey crypto.Decrypter, err error) { +func (a *Authority) selectDecrypter(ctx context.Context) (cert *x509.Certificate, decrypter crypto.Decrypter, err error) { p := provisionerFromContext(ctx) - cert, pkey = p.GetDecrypter() + cert, decrypter = p.GetDecrypter() switch { - case cert != nil && pkey != nil: + case cert != nil && decrypter != nil: return - case cert == nil && pkey != nil: + case cert == nil && decrypter != nil: return nil, nil, fmt.Errorf("provisioner %q does not have a decrypter certificate available", p.GetName()) - case cert != nil && pkey == nil: + case cert != nil && decrypter == nil: return nil, nil, fmt.Errorf("provisioner %q does not have a decrypter available", p.GetName()) } - cert, pkey = a.signerCertificate, a.defaultDecrypter + cert, decrypter = a.decrypterCertificate, a.defaultDecrypter switch { - case cert == nil && pkey != nil: + case cert == nil && decrypter != nil: return nil, nil, fmt.Errorf("provisioner %q does not have a default decrypter certificate available", p.GetName()) - case cert != nil && pkey == nil: + case cert != nil && decrypter == nil: return nil, nil, fmt.Errorf("provisioner %q does not have a default decrypter available", p.GetName()) } return } -func (a *Authority) selectSigner(ctx context.Context) (cert *x509.Certificate, pkey crypto.PrivateKey, err error) { +func (a *Authority) selectSigner(ctx context.Context) (cert *x509.Certificate, signer crypto.Signer, err error) { p := provisionerFromContext(ctx) - cert, pkey = p.GetSigner() + cert, signer = p.GetSigner() switch { - case cert != nil && pkey != nil: + case cert != nil && signer != nil: return - case cert == nil && pkey != nil: + case cert == nil && signer != nil: return nil, nil, fmt.Errorf("provisioner %q does not have a signer certificate available", p.GetName()) - case cert != nil && pkey == nil: + case cert != nil && signer == nil: return nil, nil, fmt.Errorf("provisioner %q does not have a signer available", p.GetName()) } - cert, pkey = a.signerCertificate, a.defaultSigner + cert, signer = a.signerCertificate, a.defaultSigner switch { - case cert == nil && pkey != nil: + case cert == nil && signer != nil: return nil, nil, fmt.Errorf("provisioner %q does not have a default signer certificate available", p.GetName()) - case cert != nil && pkey == nil: + case cert != nil && signer == nil: return nil, nil, fmt.Errorf("provisioner %q does not have a default signer available", p.GetName()) } diff --git a/scep/options.go b/scep/options.go index 7ba7cfc2..8bc30a61 100644 --- a/scep/options.go +++ b/scep/options.go @@ -20,6 +20,8 @@ type Options struct { Signer crypto.Signer `json:"-"` // Decrypter decrypts encrypted SCEP messages. Configured in the ca.json key property. Decrypter crypto.Decrypter `json:"-"` + // DecrypterCert points to the certificate of the CA decrypter. + DecrypterCert *x509.Certificate `json:"-"` // SCEPProvisionerNames contains the currently configured SCEP provioner names. These // are used to be able to load the provisioners when the SCEP authority is being // validated.