Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions authority/provisioner/scep.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ type SCEP struct {
// MinimumPublicKeyLength is the minimum length for public keys in CSRs
MinimumPublicKeyLength int `json:"minimumPublicKeyLength,omitempty"`

// AllowUnsortedAuthenticatedAttributes permits verification of PKCS#7 messages
// from legacy SCEP clients that sign authenticated attributes without DER sorting.
AllowUnsortedAuthenticatedAttributes bool `json:"allowUnsortedAuthenticatedAttributes,omitempty"`

// LegacyRSADigestEncryptionAlgorithm makes SCEP responses use rsaEncryption as the
// SignerInfo digestEncryptionAlgorithm for compatibility with legacy SCEP clients.
LegacyRSADigestEncryptionAlgorithm bool `json:"legacyRSADigestEncryptionAlgorithm,omitempty"`

// TODO(hs): also support a separate signer configuration?
DecrypterCertificate []byte `json:"decrypterCertificate,omitempty"`
DecrypterKeyPEM []byte `json:"decrypterKeyPEM,omitempty"`
Expand Down Expand Up @@ -447,6 +455,18 @@ func (s *SCEP) ShouldIncludeIntermediateInChain() bool {
return !s.ExcludeIntermediate
}

// ShouldAllowUnsortedAuthenticatedAttributes indicates whether verification may
// fall back to the authenticated attribute order used by legacy SCEP clients.
func (s *SCEP) ShouldAllowUnsortedAuthenticatedAttributes() bool {
return s.AllowUnsortedAuthenticatedAttributes
}

// ShouldUseLegacyRSADigestEncryptionAlgorithm indicates whether SCEP responses
// should use rsaEncryption as the SignerInfo digestEncryptionAlgorithm.
func (s *SCEP) ShouldUseLegacyRSADigestEncryptionAlgorithm() bool {
return s.LegacyRSADigestEncryptionAlgorithm
}

// GetContentEncryptionAlgorithm returns the numeric identifier
// for the pkcs7 package encryption algorithm to use.
func (s *SCEP) GetContentEncryptionAlgorithm() int {
Expand Down
5 changes: 3 additions & 2 deletions scep/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -345,8 +345,10 @@ func GetCACaps(ctx context.Context) (Response, error) {

// PKIOperation performs PKI operations and returns a SCEP response
func PKIOperation(ctx context.Context, req request) (Response, error) {
auth := scep.MustFromContext(ctx)

// parse the message using smallscep implementation
microMsg, err := smallscep.ParsePKIMessage(req.Message)
microMsg, err := smallscep.ParsePKIMessage(req.Message, smallscep.WithUnsortedAuthenticatedAttributes(auth.ShouldAllowUnsortedAuthenticatedAttributes(ctx)))
if err != nil {
// return the error, because we can't use the msg for creating a CertRep
return Response{}, fmt.Errorf("failed parsing SCEP request: %w", err)
Expand All @@ -369,7 +371,6 @@ func PKIOperation(ctx context.Context, req request) (Response, error) {
P7: p7,
}

auth := scep.MustFromContext(ctx)
if err := auth.DecryptPKIEnvelope(ctx, msg); err != nil {
return Response{}, err
}
Expand Down
17 changes: 17 additions & 0 deletions scep/authority.go
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,10 @@ func (a *Authority) SignCSR(ctx context.Context, csr *x509.CertificateRequest, m
return nil, fmt.Errorf("failed selecting signer: %w", err)
}

if p.ShouldUseLegacyRSADigestEncryptionAlgorithm() {
signedData.SetEncryptionAlgorithm(pkcs7.OIDEncryptionAlgorithmRSA)
}

// sign the attributes
if err := signedData.AddSigner(signerCert, signer, config); err != nil {
return nil, err
Expand Down Expand Up @@ -424,6 +428,8 @@ func (a *Authority) encrypt(content []byte, recipients []*x509.Certificate, algo

// CreateFailureResponse creates an appropriately signed reply for PKI operations
func (a *Authority) CreateFailureResponse(ctx context.Context, _ *x509.CertificateRequest, msg *PKIMessage, info FailInfoName, infoText string) (*PKIMessage, error) {
p := provisionerFromContext(ctx)

config := pkcs7.SignerInfoConfig{
ExtraSignedAttributes: []pkcs7.Attribute{
{
Expand Down Expand Up @@ -467,6 +473,10 @@ func (a *Authority) CreateFailureResponse(ctx context.Context, _ *x509.Certifica
return nil, fmt.Errorf("failed selecting signer: %w", err)
}

if p.ShouldUseLegacyRSADigestEncryptionAlgorithm() {
signedData.SetEncryptionAlgorithm(pkcs7.OIDEncryptionAlgorithmRSA)
}

// sign the attributes
if err := signedData.AddSigner(signerCert, signer, config); err != nil {
return nil, err
Expand Down Expand Up @@ -512,6 +522,13 @@ func (a *Authority) GetCACaps(ctx context.Context) []string {
return caps
}

// ShouldAllowUnsortedAuthenticatedAttributes indicates whether verification may
// accept authenticated attributes in their encoded order for the current provisioner.
func (a *Authority) ShouldAllowUnsortedAuthenticatedAttributes(ctx context.Context) bool {
p := provisionerFromContext(ctx)
return p.ShouldAllowUnsortedAuthenticatedAttributes()
}

func (a *Authority) ValidateChallenge(ctx context.Context, csr *x509.CertificateRequest, challenge, transactionID string) ([]provisioner.SignCSROption, error) {
p := provisionerFromContext(ctx)
return p.ValidateChallenge(ctx, csr, challenge, transactionID)
Expand Down
2 changes: 2 additions & 0 deletions scep/provisioner.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ type Provisioner interface {
GetCapabilities() []string
ShouldIncludeRootInChain() bool
ShouldIncludeIntermediateInChain() bool
ShouldAllowUnsortedAuthenticatedAttributes() bool
ShouldUseLegacyRSADigestEncryptionAlgorithm() bool
GetDecrypter() (*x509.Certificate, crypto.Decrypter)
GetSigner() (*x509.Certificate, crypto.Signer)
GetContentEncryptionAlgorithm() int
Expand Down