Skip to content
This repository has been archived by the owner on Aug 31, 2021. It is now read-only.

Commit

Permalink
[easyca] handle CAs, Intermediates, and Client
Browse files Browse the repository at this point in the history
* Split certificate type handling up, try to re-use operations where
  possible.
* Set the EKUs for client/serverauth on clients, servers, and
  Intermediate CAs
  • Loading branch information
AJ Christensen committed Oct 26, 2016
1 parent bc21028 commit ea18916
Showing 1 changed file with 35 additions and 24 deletions.
59 changes: 35 additions & 24 deletions pkg/easypki/easyca.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,48 +113,47 @@ func GenerateCertificate(genReq *GenerationRequest) error {
genReq.Template.NotBefore = time.Now()
genReq.Template.SignatureAlgorithm = x509.SHA256WithRSA

if genReq.Template.IsCA {
// Non-intermediate Certificate Authority
if genReq.Template.IsCA && !genReq.IsIntermediateCA {
// Random Serial
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
return fmt.Errorf("failed to generate ca serial number: %s", err)
}
genReq.Template.SerialNumber = serialNumber
genReq.Template.KeyUsage = x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign | x509.KeyUsageCRLSign
genReq.Template.BasicConstraintsValid = true

// Root certificate can self-sign
genReq.Template.Issuer = genReq.Template.Subject
genReq.Template.AuthorityKeyId = genReq.Template.SubjectKeyId

// if the maximum path length was provided be sure to enforce it
if genReq.MaxPathLen >= 0 {
genReq.Template.MaxPathLen = genReq.MaxPathLen
genReq.Template.MaxPathLenZero = true // doesn't force to zero
}
// Use the generated certificate template and private key (self-signing)
caCrt = genReq.Template
caKey = privateKey
}

// Intermediate-only Certificate Authority
if genReq.Template.IsCA && genReq.IsIntermediateCA {
genReq.Template.ExtKeyUsage = []x509.ExtKeyUsage{
x509.ExtKeyUsageClientAuth,
x509.ExtKeyUsageServerAuth,
}

caCrt = genReq.Template
caKey = privateKey
}

// if this is not a CA certificate...
// or if this is an intermediate certificate...
// we want to sign it with our parent CA's key
if !genReq.Template.IsCA || genReq.IsIntermediateCA {
if !genReq.IsIntermediateCA {
// set the usage for non-CA certificates
genReq.Template.KeyUsage = x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment
genReq.Template.ExtKeyUsage = append(genReq.Template.ExtKeyUsage, x509.ExtKeyUsageClientAuth)

// set UsageServerAuth only if this isn't a client cert
if !genReq.IsClientCertificate {
genReq.Template.ExtKeyUsage = append(genReq.Template.ExtKeyUsage, x509.ExtKeyUsageServerAuth)
}
// Either type of Certificate Authority (intermediate, root, etc.)
if genReq.Template.IsCA || genReq.IsIntermediateCA {
genReq.Template.KeyUsage = x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign | x509.KeyUsageCRLSign
genReq.Template.BasicConstraintsValid = true

// Enforce Maximum Path Length
if genReq.MaxPathLen >= 0 {
genReq.Template.MaxPathLen = genReq.MaxPathLen
genReq.Template.MaxPathLenZero = true // doesn't force to zero
}
}

// Any leaf: intermediate CAs, client/server certificates, signed by a root
if !genReq.Template.IsCA || genReq.IsIntermediateCA {
serialNumber, err := NextNumber(genReq.PKIRoot, "serial")
if err != nil {
return fmt.Errorf("get next serial: %v", err)
Expand All @@ -167,6 +166,18 @@ func GenerateCertificate(genReq *GenerationRequest) error {
}
}

// Should cover only client/server (All non-CA, i.e. doesn't include intermediates)
if !genReq.Template.IsCA {
if !genReq.IsClientCertificate {
genReq.Template.ExtKeyUsage = append(genReq.Template.ExtKeyUsage, x509.ExtKeyUsageServerAuth)
}
// Clients can only use ClientAuth
genReq.Template.ExtKeyUsage = append(genReq.Template.ExtKeyUsage, x509.ExtKeyUsageClientAuth)

// set the usage for non-CA certificates
genReq.Template.KeyUsage = x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment
}

crt, err := x509.CreateCertificate(rand.Reader, genReq.Template, caCrt, privateKey.Public(), caKey)
if err != nil {
return fmt.Errorf("create certificate: %v", err)
Expand Down

0 comments on commit ea18916

Please sign in to comment.