ca

package
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 3, 2026 License: MIT Imports: 19 Imported by: 0

Documentation

Overview

Package ca is the certificate authority abstraction that issues device enrollment identities: a Signer interface, a Local signer over an in-memory key constrained by a Policy, a Depot that records what was issued, and self-signed CA generation.

Why

Every MDM enrollment rests on a device identity certificate, and the server has to issue one through SCEP (phase 3) and, later, ACME (phase 7). Both endpoints need the same small thing from a CA: sign this CSR under this policy and remember the result. This package holds that contract so the protocol packages never touch a private key directly. Local signs with an in-memory RSA or ECDSA key; a deployment with an external CA implements Signer and keeps its keys where it wants them.

The package deliberately leaves out the SCEP wire protocol (scep), the ACME protocol and attestation verification (phase 7), certificate storage beyond MemoryDepot, and revocation. Policy covers only what an enrollment identity needs: validity, key size and type, key usage, and subject alternative names.

References

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrCSR      = errors.New("ca: invalid certificate signing request")
	ErrPolicy   = errors.New("ca: request violates policy")
	ErrNotFound = errors.New("ca: certificate not found")
)

Errors returned by this package.

View Source
var (
	OIDPermanentIdentifier = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 8, 3} // RFC 4043
	OIDHardwareModuleName  = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 8, 4} // RFC 4108
	OIDNTPrincipalName     = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 20, 2, 3}
)

OIDs for the otherName forms this package can build.

Functions

func NewSelfSigned

func NewSelfSigned(o SelfSignedOptions) (*x509.Certificate, *rsa.PrivateKey, error)

NewSelfSigned generates an RSA CA certificate and key, suitable as a SCEP RA/CA for a self-contained deployment.

func ParsePermanentIdentifier

func ParsePermanentIdentifier(cert *x509.Certificate) (string, bool, error)

ParsePermanentIdentifier returns the identifier value of the first RFC 4043 otherName, and whether one was present.

func SANExtension

func SANExtension(names SANs, subjectEmpty bool) (pkix.Extension, bool, error)

SANExtension builds the subjectAltName extension (OID 2.5.29.17) from otherNames plus the conventional name forms. It returns the zero Extension and false when there is nothing to encode. The extension is marked critical when the certificate's subject is empty, as RFC 5280 section 4.2.1.6 requires.

func Serial

func Serial() (*big.Int, error)

Serial returns a random 127-bit positive serial number, as CA/Browser Forum guidance recommends over counters.

func SerialFrom

func SerialFrom(r io.Reader) (*big.Int, error)

SerialFrom draws a serial from r.

Types

type Depot

type Depot interface {
	Put(ctx context.Context, cert *x509.Certificate) error
	// Get returns the certificate with the serial or ErrNotFound.
	Get(ctx context.Context, serial *big.Int) (*x509.Certificate, error)
}

Depot records issued certificates.

type KeyKind

type KeyKind string

KeyKind names a public key type and size that the CA can be told to accept.

const (
	KeyRSA2048 KeyKind = "rsa-2048"
	KeyRSA3072 KeyKind = "rsa-3072"
	KeyRSA4096 KeyKind = "rsa-4096"
	KeyECP256  KeyKind = "ec-p256"
	KeyECP384  KeyKind = "ec-p384"
	KeyECP521  KeyKind = "ec-p521"
)

The key kinds this package can name. A deployment lists the ones it approves in Policy.AllowedKeys so that a device cannot pick a key the deployment has not sanctioned.

func KindOf

func KindOf(pub crypto.PublicKey) (KeyKind, bool)

KindOf reports the KeyKind of a public key, and false for a key this package cannot describe. An RSA key of an unusual size gets no kind rather than an approximate one, so that AllowedKeys admits exactly the sizes it lists.

type Local

type Local struct {
	// contains filtered or unexported fields
}

Local is a Signer holding its key in memory.

func NewLocal

func NewLocal(cert *x509.Certificate, key crypto.Signer, opts ...Option) (*Local, error)

NewLocal creates a signer from a CA certificate and its key.

func (*Local) Certificate

func (l *Local) Certificate() *x509.Certificate

Certificate implements Signer.

func (*Local) Chain

func (l *Local) Chain() []*x509.Certificate

Chain implements Signer.

func (*Local) Sign

Sign implements Signer.

type MemoryDepot

type MemoryDepot struct {
	// contains filtered or unexported fields
}

MemoryDepot keeps issued certificates in memory.

func NewMemoryDepot

func NewMemoryDepot() *MemoryDepot

NewMemoryDepot creates an empty depot.

func (*MemoryDepot) Get

func (d *MemoryDepot) Get(_ context.Context, serial *big.Int) (*x509.Certificate, error)

Get implements Depot.

func (*MemoryDepot) Len

func (d *MemoryDepot) Len() int

Len returns how many certificates are stored.

func (*MemoryDepot) Put

func (d *MemoryDepot) Put(_ context.Context, cert *x509.Certificate) error

Put implements Depot.

type Option

type Option func(*Local)

Option configures Local.

func WithChain

func WithChain(chain ...*x509.Certificate) Option

WithChain sets intermediates returned by Chain.

func WithClock

func WithClock(c clock.Clock) Option

WithClock sets the clock (tests).

func WithDepot

func WithDepot(d Depot) Option

WithDepot records issued certificates.

func WithRandom

func WithRandom(r io.Reader) Option

WithRandom sets the entropy source for serials (tests).

type OtherName

type OtherName struct {
	ID    asn1.ObjectIdentifier
	Value []byte // the DER of the value, already encoded
}

OtherName is one GeneralName of the otherName form.

func HardwareModuleName

func HardwareModuleName(hwType asn1.ObjectIdentifier, serial []byte) (OtherName, error)

HardwareModuleName builds the RFC 4108 otherName. HardwareModuleName ::= SEQUENCE { hwType OBJECT IDENTIFIER, hwSerialNum OCTET STRING }. Both members are required.

func NTPrincipalName

func NTPrincipalName(name string) (OtherName, error)

NTPrincipalName builds the otherName Apple's ACME payload calls ntPrincipalName, a UTF8String under 1.3.6.1.4.1.311.20.2.3.

func ParseOtherNames

func ParseOtherNames(cert *x509.Certificate) ([]OtherName, error)

ParseOtherNames returns the otherName entries of a certificate's subjectAltName extension.

func PermanentIdentifier

func PermanentIdentifier(value string) (OtherName, error)

PermanentIdentifier builds the RFC 4043 otherName for an identifier value. RFC 4043: PermanentIdentifier ::= SEQUENCE { identifierValue UTF8String OPTIONAL, assigner OBJECT IDENTIFIER OPTIONAL }. When the assigner is absent the certificate issuer is the assigner.

type Policy

type Policy struct {
	// Validity of issued certificates; default one year.
	Validity time.Duration
	// NotAfter caps the expiry absolutely, whatever Validity says. A
	// deadline is a moment, not a duration: a caller that turned one into a
	// duration would have the certificate outlive it by however long
	// issuing took, which is the kind of margin that goes unnoticed until
	// it matters. Zero means Validity alone decides.
	NotAfter time.Time
	// Backdate NotBefore by this much to absorb clock skew; default 5 minutes.
	Backdate time.Duration
	// KeyUsage default: digital signature (plus key encipherment for RSA).
	KeyUsage x509.KeyUsage
	// ExtKeyUsage default: client authentication.
	ExtKeyUsage []x509.ExtKeyUsage
	// AllowSANs permits subject alternative names from the CSR. Off by
	// default: an MDM identity is named by its subject only.
	AllowSANs bool
	// MinRSABits rejects small RSA keys; default 2048.
	MinRSABits int
	// Subject replaces the certificate request's subject when set. An ACME
	// server uses this because Apple's documentation says the server may
	// override the Subject the profile asked for: the subject is the server's
	// statement about the device, not the device's claim about itself.
	Subject *pkix.Name
	// OtherNames are subjectAltName otherName entries added to the issued
	// certificate. They come from the server, not from the request, so they
	// are not subject to AllowSANs.
	OtherNames []OtherName
	// AllowedKeys restricts the key types the CA will certify. Empty means
	// the existing behaviour: any RSA key of at least MinRSABits, and any
	// ECDSA key.
	AllowedKeys []KeyKind
}

Policy constrains what Sign issues. Zero values take the defaults.

type SANs

type SANs struct {
	OtherNames     []OtherName
	DNSNames       []string
	EmailAddresses []string
	IPAddresses    []net.IP
	URIs           []*url.URL
}

SANs are the subject alternative names of an issued certificate.

type SelfSignedOptions

type SelfSignedOptions struct {
	Subject  pkix.Name
	Validity time.Duration // default 10 years
	// RSABits default 2048. SCEP requires an RSA CA because devices
	// encrypt the PKCS #7 envelope to it.
	RSABits int
	// Random defaults to crypto/rand.
	Random io.Reader
}

SelfSignedOptions configure NewSelfSigned.

type Signer

type Signer interface {
	// Sign validates the CSR against the policy and returns the issued
	// certificate.
	Sign(ctx context.Context, csr *x509.CertificateRequest, p Policy) (*x509.Certificate, error)
	// Certificate returns the CA (or RA) certificate that signs.
	Certificate() *x509.Certificate
	// Chain returns the certificate followed by any intermediates up to but
	// not including the root, for clients that need the full chain.
	Chain() []*x509.Certificate
}

Signer issues certificates.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL