Remove x509 template from API

This commit is contained in:
Herman Slatman 2021-02-26 18:07:50 +01:00
parent 311c9d767b
commit a6d50f2fa0
No known key found for this signature in database
GPG key ID: F4D8A44EA0A75A4F
2 changed files with 56 additions and 56 deletions

View file

@ -2,19 +2,14 @@ package api
import ( import (
"context" "context"
"crypto"
"crypto/sha1"
"crypto/x509" "crypto/x509"
"encoding/base64" "encoding/base64"
"errors" "errors"
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"math/big"
"math/rand"
"net/http" "net/http"
"strings" "strings"
"time"
"github.com/smallstep/certificates/acme" "github.com/smallstep/certificates/acme"
"github.com/smallstep/certificates/api" "github.com/smallstep/certificates/api"
@ -252,53 +247,29 @@ func (h *Handler) PKIOperation(w http.ResponseWriter, r *http.Request, scepReque
ctx := r.Context() ctx := r.Context()
msg, err := microscep.ParsePKIMessage(scepRequest.Message) microMsg, err := microscep.ParsePKIMessage(scepRequest.Message)
if err != nil { if err != nil {
return err return err
} }
pkimsg := &scep.PKIMessage{ msg := &scep.PKIMessage{
TransactionID: msg.TransactionID, TransactionID: microMsg.TransactionID,
MessageType: msg.MessageType, MessageType: microMsg.MessageType,
SenderNonce: msg.SenderNonce, SenderNonce: microMsg.SenderNonce,
Raw: msg.Raw, Raw: microMsg.Raw,
} }
if err := h.Auth.DecryptPKIEnvelope(ctx, pkimsg); err != nil { if err := h.Auth.DecryptPKIEnvelope(ctx, msg); err != nil {
return err return err
} }
if pkimsg.MessageType == microscep.PKCSReq { if msg.MessageType == microscep.PKCSReq {
// TODO: CSR validation, like challenge password // TODO: CSR validation, like challenge password
} }
csr := pkimsg.CSRReqMessage.CSR csr := msg.CSRReqMessage.CSR
subjectKeyID, err := createKeyIdentifier(csr.PublicKey)
if err != nil {
return err
}
serial := big.NewInt(int64(rand.Int63())) // TODO: serial logic? certRep, err := h.Auth.SignCSR(ctx, csr, msg)
days := 40
// TODO: use information from provisioner, like claims
template := &x509.Certificate{
SerialNumber: serial,
Subject: csr.Subject,
NotBefore: time.Now().Add(-600).UTC(),
NotAfter: time.Now().AddDate(0, 0, days).UTC(),
SubjectKeyId: subjectKeyID,
KeyUsage: x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{
x509.ExtKeyUsageClientAuth,
},
SignatureAlgorithm: csr.SignatureAlgorithm,
EmailAddresses: csr.EmailAddresses,
DNSNames: csr.DNSNames,
}
certRep, err := h.Auth.SignCSR(ctx, pkimsg, template)
if err != nil { if err != nil {
return err return err
} }
@ -323,20 +294,6 @@ func certName(cert *x509.Certificate) string {
return string(cert.Signature) return string(cert.Signature)
} }
// createKeyIdentifier creates an identifier for public keys
// according to the first method in RFC5280 section 4.2.1.2.
func createKeyIdentifier(pub crypto.PublicKey) ([]byte, error) {
keyBytes, err := x509.MarshalPKIXPublicKey(pub)
if err != nil {
return nil, err
}
id := sha1.Sum(keyBytes)
return id[:], nil
}
func formatCapabilities(caps []string) []byte { func formatCapabilities(caps []string) []byte {
return []byte(strings.Join(caps, "\r\n")) return []byte(strings.Join(caps, "\r\n"))
} }
@ -354,6 +311,7 @@ func writeSCEPResponse(w http.ResponseWriter, response SCEPResponse) error {
var ( var (
// TODO: check the default capabilities; https://tools.ietf.org/html/rfc8894#section-3.5.2 // TODO: check the default capabilities; https://tools.ietf.org/html/rfc8894#section-3.5.2
// TODO: move capabilities to Authority or Provisioner, so that they can be configured?
defaultCapabilities = []string{ defaultCapabilities = []string{
"Renewal", "Renewal",
"SHA-1", "SHA-1",

View file

@ -3,6 +3,8 @@ package scep
import ( import (
"bytes" "bytes"
"context" "context"
"crypto"
"crypto/sha1"
"crypto/x509" "crypto/x509"
"errors" "errors"
"fmt" "fmt"
@ -52,7 +54,7 @@ type Interface interface {
GetCACertificates() ([]*x509.Certificate, error) GetCACertificates() ([]*x509.Certificate, error)
DecryptPKIEnvelope(ctx context.Context, msg *PKIMessage) error DecryptPKIEnvelope(ctx context.Context, msg *PKIMessage) error
SignCSR(ctx context.Context, msg *PKIMessage, template *x509.Certificate) (*PKIMessage, error) SignCSR(ctx context.Context, csr *x509.CertificateRequest, msg *PKIMessage) (*PKIMessage, error)
} }
// Authority is the layer that handles all SCEP interactions. // Authority is the layer that handles all SCEP interactions.
@ -221,7 +223,8 @@ func (a *Authority) DecryptPKIEnvelope(ctx context.Context, msg *PKIMessage) err
// SignCSR creates an x509.Certificate based on a CSR template and Cert Authority credentials // SignCSR creates an x509.Certificate based on a CSR template and Cert Authority credentials
// returns a new PKIMessage with CertRep data // returns a new PKIMessage with CertRep data
//func (msg *PKIMessage) SignCSR(crtAuth *x509.Certificate, keyAuth *rsa.PrivateKey, template *x509.Certificate) (*PKIMessage, error) { //func (msg *PKIMessage) SignCSR(crtAuth *x509.Certificate, keyAuth *rsa.PrivateKey, template *x509.Certificate) (*PKIMessage, error) {
func (a *Authority) SignCSR(ctx context.Context, msg *PKIMessage, template *x509.Certificate) (*PKIMessage, error) { //func (a *Authority) SignCSR(ctx context.Context, msg *PKIMessage, template *x509.Certificate) (*PKIMessage, error) {
func (a *Authority) SignCSR(ctx context.Context, csr *x509.CertificateRequest, msg *PKIMessage) (*PKIMessage, error) {
// TODO: intermediate storage of the request? In SCEP it's possible to request a csr/certificate // TODO: intermediate storage of the request? In SCEP it's possible to request a csr/certificate
// to be signed, which can be performed asynchronously / out-of-band. In that case a client can // to be signed, which can be performed asynchronously / out-of-band. In that case a client can
@ -238,9 +241,32 @@ func (a *Authority) SignCSR(ctx context.Context, msg *PKIMessage, template *x509
if err := a.DecryptPKIEnvelope(ctx, msg); err != nil { if err := a.DecryptPKIEnvelope(ctx, msg); err != nil {
return nil, err return nil, err
} }
csr = msg.CSRReqMessage.CSR
} }
csr := msg.CSRReqMessage.CSR // subjectKeyID, err := createKeyIdentifier(csr.PublicKey)
// if err != nil {
// return nil, err
// }
// serial := big.NewInt(int64(rand.Int63())) // TODO: serial logic?
// days := 40 // TODO: days
// // TODO: use information from provisioner, like claims
// template := &x509.Certificate{
// SerialNumber: serial,
// Subject: csr.Subject,
// NotBefore: time.Now().Add(-600).UTC(),
// NotAfter: time.Now().AddDate(0, 0, days).UTC(),
// SubjectKeyId: subjectKeyID,
// KeyUsage: x509.KeyUsageDigitalSignature,
// ExtKeyUsage: []x509.ExtKeyUsage{
// x509.ExtKeyUsageClientAuth,
// },
// SignatureAlgorithm: csr.SignatureAlgorithm,
// EmailAddresses: csr.EmailAddresses,
// DNSNames: csr.DNSNames,
// }
// Template data // Template data
data := x509util.NewTemplateData() data := x509util.NewTemplateData()
@ -278,6 +304,8 @@ func (a *Authority) SignCSR(ctx context.Context, msg *PKIMessage, template *x509
// fmt.Println(fmt.Sprintf("%T", cert)) // fmt.Println(fmt.Sprintf("%T", cert))
// fmt.Println(cert.Issuer) // fmt.Println(cert.Issuer)
// fmt.Println(cert.Subject) // fmt.Println(cert.Subject)
// fmt.Println(cert.SerialNumber)
// fmt.Println(string(cert.SubjectKeyId))
// create a degenerate cert structure // create a degenerate cert structure
deg, err := DegenerateCertificates([]*x509.Certificate{cert}) deg, err := DegenerateCertificates([]*x509.Certificate{cert})
@ -365,6 +393,20 @@ func DegenerateCertificates(certs []*x509.Certificate) ([]byte, error) {
return degenerate, nil return degenerate, nil
} }
// createKeyIdentifier creates an identifier for public keys
// according to the first method in RFC5280 section 4.2.1.2.
func createKeyIdentifier(pub crypto.PublicKey) ([]byte, error) {
keyBytes, err := x509.MarshalPKIXPublicKey(pub)
if err != nil {
return nil, err
}
id := sha1.Sum(keyBytes)
return id[:], nil
}
// Interface guards // Interface guards
var ( var (
_ Interface = (*Authority)(nil) _ Interface = (*Authority)(nil)