forked from TrueCloudLab/certificates
Add validation to SCEP Options
This commit is contained in:
parent
b97f024f8a
commit
65aab963c9
1 changed files with 53 additions and 13 deletions
|
@ -2,30 +2,70 @@ package scep
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto"
|
"crypto"
|
||||||
|
"crypto/rsa"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Options struct {
|
type Options struct {
|
||||||
// CertificateChain is the issuer certificate, along with any other bundled certificates
|
// CertificateChain is the issuer certificate, along with any other bundled certificates
|
||||||
// to be returned in the chain for consumers. Configured in ca.json crt property.
|
// to be returned in the chain for consumers. Configured in the ca.json crt property.
|
||||||
CertificateChain []*x509.Certificate
|
CertificateChain []*x509.Certificate
|
||||||
// Signer signs CSRs in SCEP. Configured in ca.json key property.
|
// Signer signs CSRs in SCEP. Configured in the ca.json key property.
|
||||||
Signer crypto.Signer `json:"-"`
|
Signer crypto.Signer `json:"-"`
|
||||||
// Decrypter decrypts encrypted SCEP messages. Configured in ca.json key property.
|
// Decrypter decrypts encrypted SCEP messages. Configured in the ca.json key property.
|
||||||
Decrypter crypto.Decrypter `json:"-"`
|
Decrypter crypto.Decrypter `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate checks the fields in Options.
|
// Validate checks the fields in Options.
|
||||||
func (o *Options) Validate() error {
|
func (o *Options) Validate() error {
|
||||||
// var typ Type
|
|
||||||
// if o == nil {
|
if o.CertificateChain == nil {
|
||||||
// typ = Type(SoftCAS)
|
return errors.New("certificate chain not configured correctly")
|
||||||
// } else {
|
}
|
||||||
// typ = Type(o.Type)
|
|
||||||
// }
|
if len(o.CertificateChain) < 1 {
|
||||||
// // Check that the type can be loaded.
|
return errors.New("certificate chain should at least have one certificate")
|
||||||
// if _, ok := LoadCertificateAuthorityServiceNewFunc(typ); !ok {
|
}
|
||||||
// return errors.Errorf("unsupported cas type %s", typ)
|
|
||||||
// }
|
// According to the RFC: https://tools.ietf.org/html/rfc8894#section-3.1, SCEP
|
||||||
|
// can be used with something different than RSA, but requires the encryption
|
||||||
|
// to be performed using the challenge password. An older version of specification
|
||||||
|
// states that only RSA is supported: https://tools.ietf.org/html/draft-nourse-scep-23#section-2.1.1
|
||||||
|
// Other algorithms than RSA do not seem to be supported in certnanny/sscep, but it might work
|
||||||
|
// in micromdm/scep. Currently only RSA is allowed, but it might be an option
|
||||||
|
// to try other algorithms in the future.
|
||||||
|
intermediate := o.CertificateChain[0]
|
||||||
|
if intermediate.PublicKeyAlgorithm != x509.RSA {
|
||||||
|
return errors.New("only the RSA algorithm is (currently) supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: add checks for key usage?
|
||||||
|
|
||||||
|
signerPublicKey, ok := o.Signer.Public().(*rsa.PublicKey)
|
||||||
|
if !ok {
|
||||||
|
return errors.New("only RSA public keys are (currently) supported as signers")
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if the intermediate ca certificate has the same public key as the signer.
|
||||||
|
// According to the RFC it seems valid to have different keys for the intermediate
|
||||||
|
// and the CA signing new certificates, so this might change in the future.
|
||||||
|
if !signerPublicKey.Equal(intermediate.PublicKey) {
|
||||||
|
return errors.New("mismatch between certificate chain and signer public keys")
|
||||||
|
}
|
||||||
|
|
||||||
|
decrypterPublicKey, ok := o.Decrypter.Public().(*rsa.PublicKey)
|
||||||
|
if !ok {
|
||||||
|
return errors.New("only RSA public keys are (currently) supported as decrypters")
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if intermedate public key is the same as the decrypter public key.
|
||||||
|
// In certnanny/sscep it's mentioned that the signing key can be different
|
||||||
|
// from the decrypting (and encrypting) key. Currently that's not supported.
|
||||||
|
if !decrypterPublicKey.Equal(intermediate.PublicKey) {
|
||||||
|
return errors.New("mismatch between certificate chain and decrypter public keys")
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue