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 ¶
- Decision record 0008: docs/research/decisions/0008-scep-and-ca.md
- Plan of record: docs/research/implementation_plan.md (phase 3)
- Threat model: docs/security/threat-model.md (SCEP rows)
- End-to-end scenarios: docs/testing/e2e-scenarios.md (E2E-006)
- Apple: https://developer.apple.com/documentation/devicemanagement/managing-certificates-for-device-management-services-and-devices
- Apple: https://developer.apple.com/documentation/devicemanagement/scep
- Schema: third_party/device-management/mdm/profiles/com.apple.security.scep.yaml
Index ¶
- Variables
- func NewSelfSigned(o SelfSignedOptions) (*x509.Certificate, *rsa.PrivateKey, error)
- func ParsePermanentIdentifier(cert *x509.Certificate) (string, bool, error)
- func SANExtension(names SANs, subjectEmpty bool) (pkix.Extension, bool, error)
- func Serial() (*big.Int, error)
- func SerialFrom(r io.Reader) (*big.Int, error)
- type Depot
- type KeyKind
- type Local
- type MemoryDepot
- type Option
- type OtherName
- type Policy
- type SANs
- type SelfSignedOptions
- type Signer
Constants ¶
This section is empty.
Variables ¶
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.
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 ¶
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.
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.
type Local ¶
type Local struct {
// contains filtered or unexported fields
}
Local is a Signer holding its key in memory.
func (*Local) Certificate ¶
func (l *Local) Certificate() *x509.Certificate
Certificate implements Signer.
type MemoryDepot ¶
type MemoryDepot struct {
// contains filtered or unexported fields
}
MemoryDepot keeps issued certificates in memory.
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 WithRandom ¶
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 ¶
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 ¶
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.