mtc

package module
v0.0.0-...-0fe8a6e Latest Latest
Warning

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

Go to latest
Published: Oct 1, 2026 License: BSD-3-Clause Imports: 26 Imported by: 0

README

Merkle Tree Certificates for TLS

A Hacked up Go implementation of Merkle Tree Certificates (MTC), following

and the C2SP specifications the draft defers to for serving and cosigning logs: mtc-tlog, tlog-tiles, tlog-checkpoint, tlog-cosignature, tlog-witness and tlog-mirror.

It contains a CA, a mirror, and a verifier. The certificates it issues are accepted by OpenSSL's MTC implementation (s_client / s_server with -mtc_cas, -mtc_landmarks, -mtc_subtrees, -mtc_cosigners and -tai_chains). There is no ACME support.

The draft leaves the final OIDs and the trust_anchors codepoint to IANA; this code uses the early experimentation OIDs of -06 (1.3.6.1.4.1.44363.47.0, .47.3 and .47.4), as OpenSSL does. IANA has since assigned id-alg-mtcProof (1.3.6.1.5.5.7.6.67), id-rdna-trustAnchorID (1.3.6.1.5.5.7.25.3) and id-pe-mtcCertificationAuthority-SHA256 (1.3.6.1.5.5.7.1.38); the CA issues with the experimental OIDs, and parsing and verification accept either set (OpenSSL accepts only the experimental ones for now).

Don't use this, it's my giant hack of the cloudflare MTC just for testing. Run Away.

Overview

An MTC CA appends every certificate it issues, as an MTCLogEntry, to an append-only issuance log, a Merkle tree. A certificate is an ordinary X.509 certificate whose signatureValue holds an MTCProof instead of a signature: an inclusion proof into a subtree [start, end) of the log, and, for a standalone certificate, signatures over that subtree by cosigners (the CA itself, and mirrors or witnesses).

Every so often the CA allocates a landmark, a tree size that relying parties learn out of band. A relying party that knows the landmark's subtree hashes can accept landmark-relative certificates, which carry no signatures at all.

The CA is identified by a trust anchor ID such as 32473.1 (a relative OID under 1.3.6.1.4.1; get your own arc as a private enterprise number). Log N of CA 32473.1 has log ID 32473.1.0.N, and landmark L of that log has trust anchor ID 32473.1.1.N.L.

All cosigners, including the CA cosigner, use ML-DSA-44, as mtc-tlog requires.

Installing

Go 1.27 or later is required (for crypto/mldsa).

$ go install github.com/bob-beck/cloudflare-mtc/cmd/mtc@latest

Creating a CA

$ mtc ca -p ca new --log 1 --max-lifetime 168h --landmark-interval 1h \
    --prefix-url http://localhost:8080 32473.1

This creates the directory ca with

  • ca-key.pem -- the CA cosigner's ML-DSA-44 key (mode 0400);
  • ca-cert.pem -- the CA certificate: an RFC 9925 unsigned certificate whose subject is the CA ID, whose key is the CA cosigner key, and which carries the critical id-pe-mtcCertificationAuthority-SHA256 extension with the serial number range (Section 5.5), and, with --prefix-url, the mtc-tlog prefix URL extension;
  • config.json -- the configuration;
  • queue/, state/, certs/ and www/.

www/ is what is served at the CA prefix URL. Log N lives in www/N/ in the tlog-tiles layout: checkpoint, tile/... and tile/entries/..., plus landmarks.

Requesting certificates

Requests are queued and issued in batches. Queue a request for a key you have, or let mtc generate one:

$ mtc ca -p ca queue --key server-key.pem --generate-key p256 --dns a.example
$ mtc ca -p ca queue --key other.pem --dns b.example --ip 192.0.2.1 --lifetime 24h
$ mtc ca -p ca queue --from-x509 existing-cert.pem

--key takes a PEM public key, private key or certificate. --client makes a client certificate. --from-x509 copies the subject, key, validity length and extensions of an existing certificate, leaving out those that describe its issuer (AKI, CRL distribution points, AIA, SCTs).

mtc ca -p ca show-queue prints the number of queued requests.

Issuing

$ mtc ca -p ca issue

An issuance run (Section 6.3)

  1. appends the queued entries to the log and writes the new tiles;
  2. signs a checkpoint with the CA cosigner (a tlog-cosignature ML-DSA-44 note signature);
  3. covers the new entries with two subtrees (Section 4.5) and signs them with the CA cosigner;
  4. uploads the log to each configured mirror and obtains the mirrors' subtree cosignatures (see below);
  5. writes each standalone certificate to certs/N/<index>.pem;
  6. allocates a landmark if --landmark-interval has passed since the last one (Section 6.4.2), writes the landmark-relative certificates of the entries it covers to certs/N/<index>-landmark-<L>.pem, and publishes the active landmarks in www/N/landmarks (Section 6.4.3).

Certificates are written in the application/pem-certificate-chain-with-properties format of TAI -05, Section 7.4: a CERTIFICATE PROPERTIES block followed by the certificate. Standalone certificates carry the trust anchor ID of the CA and the group caID.2.{0-}.{0-}; landmark-relative ones carry the landmark's trust anchor ID, the group caID.2.N.{L-} and trust_anchor_negotiation (Section 8.2.1).

--now sets the time used, for testing.

Inspect a certificate:

$ mtc inspect cert ca/certs/1/0.pem
$ mtc inspect landmarks ca/www/1/landmarks

Serving the CA

$ mtc ca -p ca serve --listen localhost:8080 --issue-every 10s

This serves, at the root of the listen address:

  • /ca-cert.pem
  • /<log>/checkpoint, /<log>/tile/... -- the log as tlog-tiles;
  • /<log>/landmarks -- the active landmarks;
  • /<log>/cert/<index> -- the standalone certificate;
  • /<log>/cert/<index>/landmark -- the landmark-relative certificate, or 202 Accepted with Retry-After while there is none yet (Section 9);
  • POST /queue -- queue a request: a PEM certificate to use as a template, or a PEM public key with ?dns= names.

and issues every --issue-every.

Mirrors

A mirror (tlog-mirror) keeps a verified copy of the CA's log, serves it, and cosigns checkpoints and subtrees with its own ML-DSA-44 key, so that relying parties can require a quorum of cosigners besides the CA.

$ mtc mirror -p mirror new 32473.2
$ mtc mirror -p mirror add-log --log 1 ca/ca-cert.pem
$ mtc mirror -p mirror serve --listen localhost:8081 &
$ mtc ca -p ca add-mirror --required http://localhost:8081 mirror/cosigner-cert.pem

mirror new writes mirror/cosigner-cert.pem, a certificate for the mirror's cosigner ID and key in the form OpenSSL's -mtc_cosigners reads. The mirror accepts the configured log number and the next few, as mtc-tlog asks.

From then on, each issuance run pushes the log to the mirror with tlog-mirror's add-checkpoint and add-entries, and asks for the subtree cosignatures with tlog-witness's sign-subtree. The mirror serves each log at /<hex SHA-256 of the log origin>/, with a checkpoint carrying both the CA's and the mirror's signatures.

The tlog machinery (checkpoints, note signatures, cosignatures, tiles, subtree hashes and proofs) is torchwood and golang.org/x/mod/sumdb.

Verifying

$ mtc verify --ca-cert ca/ca-cert.pem ca/certs/1/0.pem
$ mtc verify --ca-cert ca/ca-cert.pem --cosigner-cert mirror/cosigner-cert.pem --quorum 1 ca/certs/1/0.pem
$ mtc verify --ca-cert ca/ca-cert.pem --subtrees subtrees-1.txt ca/certs/1/0-landmark-1.pem

This checks the MTCProof as in Section 7.2 and the validity period, and nothing else (no name or key usage checks). A standalone certificate needs a valid CA cosignature plus --quorum valid signatures from the --cosigner-cert cosigners. A certificate whose subtree is in --subtrees is checked against that hash instead.

Using the certificates with OpenSSL

mtc ca export-openssl writes what OpenSSL's MTC options take:

$ mtc ca -p ca export-openssl -o ossl
  • ossl/ca-cert.pem for -mtc_cas;
  • ossl/cosigners.pem (mirror cosigner certificates) for -mtc_cosigners;
  • ossl/landmarks-N.txt for -mtc_landmarks <CA ID>:N:ossl/landmarks-N.txt;
  • ossl/subtrees-N.txt for -mtc_subtrees.

The subtree hashes come from the CA's own log. A real relying party gets landmark subtrees from the log and checks them against a cosigned checkpoint with subtree consistency proofs (Section 7.4).

A server with a standalone and a landmark-relative certificate for the same key, and a client that trusts the CA:

$ cat ca/certs/1/0-landmark-1.pem server-key.pem > chains.pem
$ cat ca/certs/1/0.pem server-key.pem >> chains.pem
$ openssl s_server -tls1_3 -cert fallback.pem -key fallback-key.pem \
    -tai_chains chains.pem
$ openssl s_client -tls1_3 -no-CAfile -no-CApath -no-CAstore \
    -mtc_cas ossl/ca-cert.pem \
    -mtc_landmarks 32473.1:1:ossl/landmarks-1.txt \
    -mtc_subtrees ossl/subtrees-1.txt

With the landmark subtrees loaded the client advertises the landmark group and gets the landmark-relative certificate; without them it gets the standalone one.

Code layout

  • github.com/bob-beck/cloudflare-mtc -- the formats: trust anchor IDs and patterns, certificate property lists, MTCLogEntry, MTCProof, certificate and CA certificate construction, landmarks, cosigners, and verification.
  • ca -- the CA.
  • mirror -- the tlog-mirror mirror.
  • internal/tlogstore -- a tlog-tiles log on the local filesystem.
  • cmd/mtc -- the command line tool.

testdata/openssl holds certificates generated by the draft's reference tool, taken from OpenSSL's tests; the unit tests verify them.

Documentation

Index

Constants

View Source
const (
	EntryTypeNull    = 0
	EntryTypeTBSCert = 1

	// MaxLogEntries is the maximum number of entries in a log, 2^48-1.
	MaxLogEntries = uint64(1)<<48 - 1
)

MTCLogEntryType values.

See draft-ietf-plants-merkle-tree-certs-06, Section 5.2.1.

View Source
const (
	PropertyTrustAnchorID          = 0
	PropertyTrustAnchorGroups      = 1
	PropertyTrustAnchorNegotiation = 2
)

Certificate property types.

See draft-ietf-tls-trust-anchor-ids-05, Section 7.

View Source
const PEMTypeCertificateProperties = "CERTIFICATE PROPERTIES"

PEMTypeCertificateProperties is the PEM label of a serialized CertificatePropertyList.

See draft-ietf-tls-trust-anchor-ids-05, Section 7.4.

Variables

View Source
var (
	// OIDMTCProof is id-alg-mtcProof (Section 6.2).
	OIDMTCProof = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 44363, 47, 0}

	// OIDRDNATrustAnchorID is id-rdna-trustAnchorID (Section 5.1). Its
	// value is a RELATIVE-OID.
	OIDRDNATrustAnchorID = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 44363, 47, 3}

	// OIDMTCCertificationAuthoritySHA256 is
	// id-pe-mtcCertificationAuthority-SHA256 (Section 5.5).
	OIDMTCCertificationAuthoritySHA256 = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 44363, 47, 4}

	// OIDMTCProofIANA is the IANA-assigned id-alg-mtcProof,
	// 1.3.6.1.5.5.7.6.67.
	OIDMTCProofIANA = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 6, 67}

	// OIDRDNATrustAnchorIDIANA is the IANA-assigned id-rdna-trustAnchorID,
	// 1.3.6.1.5.5.7.25.3.
	OIDRDNATrustAnchorIDIANA = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 25, 3}

	// OIDMTCCertificationAuthoritySHA256IANA is the IANA-assigned
	// id-pe-mtcCertificationAuthority-SHA256, 1.3.6.1.5.5.7.1.38.
	OIDMTCCertificationAuthoritySHA256IANA = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 38}

	// OIDMTCTlogPrefixURL is id-mtcTlogPrefixURL from c2sp.org/mtc-tlog: a
	// non-critical CA certificate extension holding the CA prefix URL as an
	// IA5String.
	OIDMTCTlogPrefixURL = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 64829, 2, 1}

	// OIDAlgUnsigned is id-alg-unsigned (RFC 9925).
	OIDAlgUnsigned = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 6, 36}

	// OIDRDNAUnsigned is id-rdna-unsigned (RFC 9925).
	OIDRDNAUnsigned = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 25, 1}

	// OIDMLDSA44 is id-ml-dsa-44 (RFC 9881).
	OIDMLDSA44 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 3, 17}
)

Object identifiers used by Merkle Tree Certificates.

OIDMTCProof, OIDRDNATrustAnchorID and OIDMTCCertificationAuthoritySHA256 are the early experimentation OIDs of draft-ietf-plants-merkle-tree-certs-06, Sections 5.1, 5.5 and 6.2, and are what this package issues, as does OpenSSL's MTC implementation. The OIDs IANA assigned for the same purposes are the ...IANA variables. Parsing and verification accept either set.

View Source
var ExperimentalOIDs = OIDSet{
	MTCProof:                        OIDMTCProof,
	RDNATrustAnchorID:               OIDRDNATrustAnchorID,
	MTCCertificationAuthoritySHA256: OIDMTCCertificationAuthoritySHA256,
}

ExperimentalOIDs are the draft experimental OIDs, which this package issues.

View Source
var IANAOIDs = OIDSet{
	MTCProof:                        OIDMTCProofIANA,
	RDNATrustAnchorID:               OIDRDNATrustAnchorIDIANA,
	MTCCertificationAuthoritySHA256: OIDMTCCertificationAuthoritySHA256IANA,
}

IANAOIDs are the IANA-assigned OIDs.

Functions

func CompareCosignerIDs

func CompareCosignerIDs(a, b TrustAnchorID) int

CompareCosignerIDs orders trust anchor IDs as required for MTCProof signatures: shorter first, then lexicographically.

See draft-ietf-plants-merkle-tree-certs-06, Section 6.2.

func DescribeOID

func DescribeOID(oid asn1.ObjectIdentifier) string

DescribeOID returns the dotted form of oid followed by its name, if it is one of the OIDs above, such as "1.3.6.1.4.1.44363.47.0 id-alg-mtcProof (draft experimental)".

func EncodePEMChainWithProperties

func EncodePEMChainWithProperties(props *CertificatePropertyList, chain ...[]byte) ([]byte, error)

EncodePEMChainWithProperties returns a certification path in the application/pem-certificate-chain-with-properties format: a CERTIFICATE PROPERTIES block followed by each certificate, end-entity first, without the trust anchor.

See draft-ietf-tls-trust-anchor-ids-05, Section 7.4.

func EntryHash

func EntryHash(entry []byte) tlog.Hash

EntryHash returns the Merkle tree leaf hash of a serialized MTCLogEntry, SHA-256(0x00 || entry).

func FindSubtrees

func FindSubtrees(start, end uint64) (Subtree, Subtree, error)

FindSubtrees returns the two subtrees that cover [start, end), per draft-ietf-plants-merkle-tree-certs-06, Section 4.5.1. The second may be empty.

func GenerateCosignerKey

func GenerateCosignerKey() (*mldsa.PrivateKey, error)

GenerateCosignerKey returns a new random ML-DSA-44 key.

func IsMTCCAExtension

func IsMTCCAExtension(oid asn1.ObjectIdentifier) bool

IsMTCCAExtension reports whether oid is id-pe-mtcCertificationAuthority-SHA256, experimental or IANA.

func IsMTCProofOID

func IsMTCProofOID(oid asn1.ObjectIdentifier) bool

IsMTCProofOID reports whether oid is id-alg-mtcProof, experimental or IANA.

func IsTrustAnchorIDAttribute

func IsTrustAnchorIDAttribute(oid asn1.ObjectIdentifier) bool

IsTrustAnchorIDAttribute reports whether oid is id-rdna-trustAnchorID, experimental or IANA.

func LandmarkSubtrees

func LandmarkSubtrees(prevTreeSize, treeSize uint64) (Subtree, Subtree, error)

LandmarkSubtrees returns the two subtrees of landmark l, given the tree size of the previous landmark.

See draft-ietf-plants-merkle-tree-certs-06, Section 6.4.2.

func LoadPrivateKeyFile

func LoadPrivateKeyFile(path string) (*mldsa.PrivateKey, error)

LoadPrivateKeyFile reads a PKCS#8 PEM ML-DSA-44 private key from a file.

func MarshalCACertificate

func MarshalCACertificate(p *CAParams) ([]byte, error)

MarshalCACertificate returns the CA certificate for p: an RFC 9925 unsigned certificate whose subject is the CA ID, whose key is the CA cosigner key, and which carries the critical id-pe-mtcCertificationAuthority-SHA256 extension.

See draft-ietf-plants-merkle-tree-certs-06, Section 5.5.

func MarshalCertificate

func MarshalCertificate(tbs []byte, proof *MTCProof) ([]byte, error)

MarshalCertificate assembles an MTC certificate from its TBSCertificate and MTCProof: the signatureAlgorithm is the TBSCertificate's signature field, which must be id-alg-mtcProof, and the signatureValue holds the serialized MTCProof.

See draft-ietf-plants-merkle-tree-certs-06, Section 6.2.

func MarshalCosignerCertificate

func MarshalCosignerCertificate(c *CosignerPublic, notBefore, notAfter time.Time) ([]byte, error)

MarshalCosignerCertificate returns a certificate representing an additional cosigner: the CA certificate's unsigned shape, with the cosigner ID as subject and the cosigner key, and no extensions. The draft does not define this; it is the form OpenSSL's OSSL_MTC_COSIGNER_parse_certificates() reads.

func MarshalLandmarks

func MarshalLandmarks(landmarks []Landmark, now time.Time) ([]byte, error)

MarshalLandmarks returns the published form of a landmark sequence: the latest landmark number, then one line per landmark, newest first, with its tree size and expiry, down to and including the first landmark that has expired at time now. landmarks is ordered oldest first and must start at landmark 0.

See draft-ietf-plants-merkle-tree-certs-06, Section 6.4.3.

func MarshalNullEntry

func MarshalNullEntry() []byte

MarshalNullEntry returns an MTCLogEntry of type null_entry with no extensions.

func MarshalPrivateKeyPEM

func MarshalPrivateKeyPEM(key *mldsa.PrivateKey) ([]byte, error)

MarshalPrivateKeyPEM encodes an ML-DSA private key as a PKCS#8 PEM block.

func MarshalTrustAnchorIDName

func MarshalTrustAnchorIDName(id TrustAnchorID) []byte

MarshalTrustAnchorIDName returns the DER Name that identifies the MTC CA (or cosigner) id: a single RDN with a single id-rdna-trustAnchorID attribute whose value is a RELATIVE-OID.

See draft-ietf-plants-merkle-tree-certs-06, Section 5.1.

func ParsePrivateKeyPEM

func ParsePrivateKeyPEM(data []byte) (*mldsa.PrivateKey, error)

ParsePrivateKeyPEM parses a PKCS#8 PEM ML-DSA-44 private key.

func RawSubtreeSignature

func RawSubtreeSignature(line string, id TrustAnchorID) ([]byte, error)

RawSubtreeSignature extracts the raw signature from a note signature line "— <name> base64(key hash || timestamp || signature)\n" as returned by a tlog-witness sign-subtree call. The timestamp must be zero and the name must be the cosigner name of id.

func SameTBSFields

func SameTBSFields(a, b *TBSCertificate) bool

SameTBSFields reports whether two parsed TBSCertificates agree on every field that enters the log entry.

func Serial

func Serial(logNumber uint16, index uint64) uint64

Serial returns the serial number of index in log logNumber, logNumber << 48 | index.

See draft-ietf-plants-merkle-tree-certs-06, Section 6.2.

Types

type CAParams

type CAParams struct {
	ID TrustAnchorID

	// Key is the CA cosigner's public key.
	Key crypto.PublicKey

	// MinSerial and MaxSerial bound the serial numbers the CA issues; both
	// are at least 2^48.
	MinSerial, MaxSerial uint64

	NotBefore, NotAfter time.Time

	// PrefixURL, if set, is the c2sp.org/mtc-tlog CA prefix URL, carried in
	// a non-critical extension.
	PrefixURL string

	// IANA writes the IANA-assigned OIDs rather than the draft's.
	IANA bool
}

A CAParams describes an MTC CA for its CA certificate.

type CertificatePropertyList

type CertificatePropertyList struct {
	// TrustAnchorID is the trust_anchor_id property, if non-empty.
	TrustAnchorID TrustAnchorID

	// TrustAnchorGroups is the trust_anchor_groups property, if non-empty.
	TrustAnchorGroups []TrustAnchorIDPattern

	// TrustAnchorNegotiation is the trust_anchor_negotiation property.
	TrustAnchorNegotiation bool
}

A CertificatePropertyList holds the certificate properties of a certification path.

See draft-ietf-tls-trust-anchor-ids-05, Section 7.

func LandmarkProperties

func LandmarkProperties(caID TrustAnchorID, logNumber uint16, landmark uint64) (*CertificatePropertyList, error)

LandmarkProperties returns the certificate properties of a landmark-relative certificate for landmark L of log N: the landmark's trust anchor ID, the group caID.2.N.{L-}, and trust_anchor_negotiation.

See draft-ietf-plants-merkle-tree-certs-06, Section 8.2.1.

func StandaloneProperties

func StandaloneProperties(caID TrustAnchorID) (*CertificatePropertyList, error)

StandaloneProperties returns the certificate properties of a standalone certificate issued by the CA caID: the CA's trust anchor ID and the group caID.2.{0-}.{0-}.

See draft-ietf-plants-merkle-tree-certs-06, Section 8.2.1.

func (*CertificatePropertyList) MarshalBinary

func (l *CertificatePropertyList) MarshalBinary() ([]byte, error)

MarshalBinary returns the serialized CertificatePropertyList.

func (*CertificatePropertyList) UnmarshalBinary

func (l *CertificatePropertyList) UnmarshalBinary(data []byte) error

UnmarshalBinary parses a serialized CertificatePropertyList. Properties must be sorted by type without duplicates; unknown types are ignored.

type Cosigner

type Cosigner struct {
	ID  TrustAnchorID
	Key *mldsa.PrivateKey
	// contains filtered or unexported fields
}

A Cosigner is an MTC cosigner holding its private key: a CA cosigner, a mirror, or a witness.

Cosigners use ML-DSA-44 and the subtree/v1 cosigned message, which is both the MTC signature format (draft-ietf-plants-merkle-tree-certs-06, Section 5.3.1) and the ML-DSA-44 cosignature of c2sp.org/tlog-cosignature, as c2sp.org/mtc-tlog requires.

func NewCosigner

func NewCosigner(id TrustAnchorID, key *mldsa.PrivateKey) (*Cosigner, error)

NewCosigner returns a Cosigner with the given ID and ML-DSA-44 key.

func (*Cosigner) NoteSigner

func (c *Cosigner) NoteSigner() *torchwood.CosignatureSigner

NoteSigner returns the cosigner as a note.Signer, which produces timestamped checkpoint cosignatures.

func (*Cosigner) Public

func (c *Cosigner) Public() *CosignerPublic

Public returns the public half of c.

func (*Cosigner) SignSubtree

func (c *Cosigner) SignSubtree(logID TrustAnchorID, start, end uint64, hash tlog.Hash) ([]byte, error)

SignSubtree returns the raw ML-DSA-44 signature over the subtree/v1 cosigned message for subtree [start, end) of log logID, with timestamp zero, as it goes in an MTCProof SubtreeSignature.

type CosignerPublic

type CosignerPublic struct {
	ID  TrustAnchorID
	Key *mldsa.PublicKey
	// contains filtered or unexported fields
}

A CosignerPublic is a cosigner's ID and public key.

func NewCosignerPublic

func NewCosignerPublic(id TrustAnchorID, key crypto.PublicKey) (*CosignerPublic, error)

NewCosignerPublic returns the public cosigner with the given ID and key.

func ParseCosignerCertificate

func ParseCosignerCertificate(der []byte) (*CosignerPublic, error)

ParseCosignerCertificate parses a certificate of the form written by MarshalCosignerCertificate.

func (*CosignerPublic) NoteVerifier

func (c *CosignerPublic) NoteVerifier() *torchwood.CosignatureVerifier

NoteVerifier returns the cosigner as a note.Verifier for checkpoint cosignatures.

func (*CosignerPublic) VerifySubtree

func (c *CosignerPublic) VerifySubtree(logID TrustAnchorID, start, end uint64, hash tlog.Hash, sig []byte) bool

VerifySubtree reports whether sig is a valid raw signature by c over subtree [start, end) of log logID with the given hash, timestamp zero.

type Landmark

type Landmark struct {
	// Number is the landmark number. Landmark 0 has tree size 0 and is never
	// active.
	Number uint64

	// TreeSize is the tree size of the landmark; tree sizes strictly
	// increase with the landmark number.
	TreeSize uint64

	// Expiry is the time, in POSIX seconds, after which the landmark is no
	// longer active. It is at least the notAfter of every entry below
	// TreeSize.
	Expiry int64
}

A Landmark is an agreed-upon tree size of an issuance log.

See draft-ietf-plants-merkle-tree-certs-06, Section 6.4.1.

func ParseLandmarks

func ParseLandmarks(data []byte, now time.Time) ([]Landmark, error)

ParseLandmarks parses the published form of a landmark sequence. It returns the landmarks it lists, newest first, including the final expired one. It checks that tree sizes strictly decrease and expiries do not increase, and that the list ends in a landmark that has expired at time now or in landmark 0.

See draft-ietf-plants-merkle-tree-certs-06, Section 6.4.3.

func (*Landmark) Active

func (l *Landmark) Active(now time.Time) bool

Active reports whether l is active at time now.

type MTCProof

type MTCProof struct {
	// Extensions is the contents of the MTCLogEntryExtension vector, equal
	// to the log entry's extensions.
	Extensions     []byte
	Start, End     uint64
	InclusionProof []tlog.Hash
	// Signatures are sorted by CompareCosignerIDs, without duplicates.
	// A landmark-relative certificate has none.
	Signatures []SubtreeSignature
}

An MTCProof is the signatureValue of a Merkle Tree Certificate.

See draft-ietf-plants-merkle-tree-certs-06, Section 6.2.

func (*MTCProof) MarshalBinary

func (p *MTCProof) MarshalBinary() ([]byte, error)

MarshalBinary serializes p. It sorts the signatures and rejects duplicate cosigner IDs.

func (*MTCProof) UnmarshalBinary

func (p *MTCProof) UnmarshalBinary(data []byte) error

UnmarshalBinary parses a serialized MTCProof strictly: no trailing data, a whole number of hashes in the inclusion proof, and signatures in strictly increasing cosigner ID order.

type OIDSet

type OIDSet struct {
	MTCProof                        asn1.ObjectIdentifier
	RDNATrustAnchorID               asn1.ObjectIdentifier
	MTCCertificationAuthoritySHA256 asn1.ObjectIdentifier
}

An OIDSet is the set of OIDs a certificate is written with.

type ParsedLogEntry

type ParsedLogEntry struct {
	Extensions []byte // contents of the extensions vector
	Type       uint16
	Data       []byte // tbs_cert_entry_data, for type tbs_cert_entry
}

ParsedLogEntry is a parsed MTCLogEntry.

func ParseLogEntry

func ParseLogEntry(entry []byte) (*ParsedLogEntry, error)

ParseLogEntry parses a serialized MTCLogEntry.

type PatternRange

type PatternRange struct {
	Min, Max uint64
	Infinite bool
}

A PatternRange is one component of a TrustAnchorIDPattern: the inclusive range [Min, Max], where Infinite means there is no upper bound.

type RevokedRange

type RevokedRange struct {
	CAID       TrustAnchorID
	Start, End uint64
}

A RevokedRange is a revoked range [Start, End) of serial numbers.

type Subtree

type Subtree struct {
	Start, End uint64
}

A Subtree is a subtree [Start, End) of an issuance log.

func (Subtree) Contains

func (s Subtree) Contains(index uint64) bool

Contains reports whether index is in s.

func (Subtree) Empty

func (s Subtree) Empty() bool

Empty reports whether s contains no entries.

type SubtreeSignature

type SubtreeSignature struct {
	CosignerID TrustAnchorID
	Signature  []byte
}

A SubtreeSignature is a cosignature in an MTCProof.

type TBSCertificate

type TBSCertificate struct {
	Raw          []byte
	Version      []byte // empty if absent (v1)
	SerialNumber []byte
	Signature    []byte
	Issuer       []byte
	Validity     []byte
	Subject      []byte
	SPKI         []byte
	SPKIAlg      []byte // SubjectPublicKeyInfo.algorithm
	// Rest is everything after the SubjectPublicKeyInfo: issuerUniqueID,
	// subjectUniqueID and extensions, as they appear in the TBSCertificate.
	Rest []byte
}

A TBSCertificate is a parsed TBSCertificate, holding each field as its complete DER encoding (tag, length and contents).

func ParseTBSCertificate

func ParseTBSCertificate(der []byte) (*TBSCertificate, error)

ParseTBSCertificate splits a DER TBSCertificate into its fields. It checks the structure but not the contents of each field.

func (*TBSCertificate) LogEntry

func (t *TBSCertificate) LogEntry(extensions []byte) ([]byte, error)

LogEntry returns the MTCLogEntry of type tbs_cert_entry that corresponds to t, with the given entry extensions (the serialized MTCLogEntryExtension vector contents, usually empty).

The TBSCertificateLogEntry holds the fields of the TBSCertificate except serialNumber and signature, with subjectPublicKeyInfo replaced by its algorithm and the hash of its DER encoding. The entry carries its contents octets only, without the outer SEQUENCE header.

See draft-ietf-plants-merkle-tree-certs-06, Sections 5.2.1 and 7.2.

func (*TBSCertificate) SerialUint64

func (t *TBSCertificate) SerialUint64() (uint64, error)

SerialUint64 returns the serial number of an MTC certificate as a uint64.

type Template

type Template struct {
	// Subject is the DER Name of the subject. An empty Subject is the
	// empty Name.
	Subject []byte

	// SPKI is the DER SubjectPublicKeyInfo.
	SPKI []byte

	NotBefore, NotAfter time.Time

	// Rest is the DER of the TBSCertificate fields after the
	// subjectPublicKeyInfo: optional unique identifiers and the [3]
	// extensions, exactly as they appear in the TBSCertificate.
	Rest []byte

	// IANA writes the IANA-assigned OIDs rather than the draft's.
	IANA bool
}

A Template holds the parts of a certificate that the subscriber chooses.

func NewTemplateFromCertificate

func NewTemplateFromCertificate(cert *x509.Certificate) (*Template, error)

NewTemplateFromCertificate returns a Template with the subject, public key, validity and extensions of an existing certificate, leaving out extensions that describe its issuer or its signature.

func NewTemplateFromX509

func NewTemplateFromX509(tmpl *x509.Certificate, pub crypto.PublicKey) (*Template, error)

NewTemplateFromX509 returns a Template with the subject and extensions that crypto/x509 produces for tmpl (DNSNames, IPAddresses, KeyUsage, ExtKeyUsage, BasicConstraints and so on), and the given public key. tmpl.NotBefore and tmpl.NotAfter are copied.

func (*Template) MarshalTBSCertificate

func (tmpl *Template) MarshalTBSCertificate(caID TrustAnchorID, serial uint64) ([]byte, error)

MarshalTBSCertificate returns the TBSCertificate of the MTC certificate for tmpl issued by caID with the given serial number.

See draft-ietf-plants-merkle-tree-certs-06, Section 6.2.

type TrustAnchorID

type TrustAnchorID []byte

A TrustAnchorID is a trust anchor identifier in its binary representation: the contents octets of a RELATIVE-OID relative to 1.3.6.1.4.1, i.e. the base-128 encoding of each component, concatenated.

See draft-ietf-tls-trust-anchor-ids-05, Section 4.

func LandmarkGroupID

func LandmarkGroupID(caID TrustAnchorID, logNumber uint16, landmark uint64) TrustAnchorID

LandmarkGroupID returns the trust anchor ID {caID landmarkGroups(2) N L} that a relying party sends when its latest trusted landmark of log N is L.

See draft-ietf-plants-merkle-tree-certs-06, Section 8.2.1.

func LandmarkID

func LandmarkID(caID TrustAnchorID, logNumber uint16, landmark uint64) TrustAnchorID

LandmarkID returns the trust anchor ID {caID landmarks(1) N L} of landmark L of log N.

See draft-ietf-plants-merkle-tree-certs-06, Section 8.2.

func LogID

func LogID(caID TrustAnchorID, logNumber uint16) TrustAnchorID

LogID returns the log ID {caID logs(0) N} of log number logNumber.

See draft-ietf-plants-merkle-tree-certs-06, Section 5.2.

func MustParseTrustAnchorID

func MustParseTrustAnchorID(s string) TrustAnchorID

MustParseTrustAnchorID is like ParseTrustAnchorID but panics on error.

func ParseTrustAnchorID

func ParseTrustAnchorID(s string) (TrustAnchorID, error)

ParseTrustAnchorID parses the ASCII representation of a trust anchor ID, such as "32473.1".

func ParseTrustAnchorIDName

func ParseTrustAnchorIDName(der []byte) (TrustAnchorID, error)

ParseTrustAnchorIDName parses a DER Name holding a single trust anchor ID attribute, experimental or IANA, and returns the trust anchor ID.

func ParseTrustAnchorIDNameOID

func ParseTrustAnchorIDNameOID(der []byte) (TrustAnchorID, asn1.ObjectIdentifier, error)

ParseTrustAnchorIDNameOID parses a DER Name holding a single trust anchor ID attribute, with either the draft experimental or the IANA-assigned id-rdna-trustAnchorID, and returns the ID and the attribute OID.

func (TrustAnchorID) Child

func (id TrustAnchorID) Child(components ...uint64) TrustAnchorID

Child returns id with the given components appended.

func (TrustAnchorID) Components

func (id TrustAnchorID) Components() ([]uint64, error)

Components returns the components of id.

func (TrustAnchorID) Equal

func (id TrustAnchorID) Equal(other TrustAnchorID) bool

Equal reports whether id and other are the same trust anchor ID.

func (TrustAnchorID) OriginString

func (id TrustAnchorID) OriginString() string

OriginString returns the representation of id used as a checkpoint origin and cosigner name: "oid/1.3.6.1.4.1." followed by the ASCII representation.

See draft-ietf-plants-merkle-tree-certs-06, Section 5.3.1, and c2sp.org/mtc-tlog.

func (TrustAnchorID) String

func (id TrustAnchorID) String() string

String returns the ASCII representation of id, such as "32473.1".

func (TrustAnchorID) Validate

func (id TrustAnchorID) Validate() error

Validate checks that id is a well-formed binary trust anchor ID.

type TrustAnchorIDPattern

type TrustAnchorIDPattern []PatternRange

A TrustAnchorIDPattern matches trust anchor IDs with the same number of components, each within the corresponding range.

See draft-ietf-tls-trust-anchor-ids-05, Section 5.3.1.

func ExactPattern

func ExactPattern(id TrustAnchorID, more ...PatternRange) (TrustAnchorIDPattern, error)

ExactPattern returns the pattern that matches exactly id, with further components appended.

func ParseTrustAnchorIDPattern

func ParseTrustAnchorIDPattern(s string) (TrustAnchorIDPattern, error)

ParseTrustAnchorIDPattern parses the text form of a pattern, in which each dot-separated component is "v", "{min-max}" or "{min-}". For example "32473.1.2.{0-}.{0-}".

func (TrustAnchorIDPattern) Contains

func (p TrustAnchorIDPattern) Contains(id TrustAnchorID) bool

Contains reports whether id matches p.

func (TrustAnchorIDPattern) MarshalBinary

func (p TrustAnchorIDPattern) MarshalBinary() ([]byte, error)

MarshalBinary returns the binary form of p: for each component, the base-128 minimum followed by the base-128 maximum, with the single byte 0x80 standing for an infinite maximum.

See draft-ietf-tls-trust-anchor-ids-05, Section 5.3.1.

func (TrustAnchorIDPattern) String

func (p TrustAnchorIDPattern) String() string

String returns the text form of p.

func (*TrustAnchorIDPattern) UnmarshalBinary

func (p *TrustAnchorIDPattern) UnmarshalBinary(b []byte) error

UnmarshalBinary parses the binary form of a pattern.

type TrustedCA

type TrustedCA struct {
	ID TrustAnchorID

	// Cosigner is the CA cosigner.
	Cosigner *CosignerPublic

	// MinSerial and MaxSerial bound the serial numbers the relying party
	// accepts from this CA.
	MinSerial, MaxSerial uint64

	// PrefixURL is the c2sp.org/mtc-tlog CA prefix URL, if the CA
	// certificate carries one.
	PrefixURL string
}

A TrustedCA is an MTC CA as configured at a relying party.

func ParseCACertificate

func ParseCACertificate(der []byte) (*TrustedCA, error)

ParseCACertificate parses an MTC CA certificate: its subject is the CA ID, its key the CA cosigner key, and its critical id-pe-mtcCertificationAuthority-SHA256 extension holds the serial range.

See draft-ietf-plants-merkle-tree-certs-06, Section 5.5.

type TrustedSubtree

type TrustedSubtree struct {
	CAID      TrustAnchorID
	LogNumber uint16
	Subtree
	Hash tlog.Hash
}

A TrustedSubtree is a subtree hash a relying party has obtained out of band, typically a landmark subtree.

See draft-ietf-plants-merkle-tree-certs-06, Section 7.4.

type VerifyOptions

type VerifyOptions struct {
	CAs             []*TrustedCA
	Cosigners       []*CosignerPublic
	TrustedSubtrees []TrustedSubtree
	Revoked         []RevokedRange

	// Quorum is the number of valid signatures from Cosigners, in addition
	// to the CA cosigner's, that a certificate needs when it does not match
	// a trusted subtree.
	Quorum int

	// CurrentTime is the time at which the validity period is checked. If
	// zero, the current time is used.
	CurrentTime time.Time
}

VerifyOptions configures Verify.

type VerifyResult

type VerifyResult struct {
	CA        *TrustedCA
	LogNumber uint16
	Index     uint64
	Proof     *MTCProof
	Subtree   Subtree
	// TrustedSubtree reports whether the certificate matched a trusted
	// subtree; otherwise it was accepted on its signatures.
	TrustedSubtree bool
	// Cosigners are the IDs of the cosigners whose valid signatures were
	// counted.
	Cosigners []TrustAnchorID
}

VerifyResult describes a verified certificate.

func Verify

func Verify(der []byte, opts *VerifyOptions) (*VerifyResult, error)

Verify checks the MTCProof of an MTC certificate and its validity period. It does not check anything else, such as names or key usage.

See draft-ietf-plants-merkle-tree-certs-06, Section 7.2.

Directories

Path Synopsis
Package ca implements a Merkle Tree Certificate CA following draft-ietf-plants-merkle-tree-certs-06, serving its issuance log as a tiled transparency log per c2sp.org/mtc-tlog.
Package ca implements a Merkle Tree Certificate CA following draft-ietf-plants-merkle-tree-certs-06, serving its issuance log as a tiled transparency log per c2sp.org/mtc-tlog.
cmd
mtc command
Command mtc runs a Merkle Tree Certificate CA and mirror, and verifies certificates, following draft-ietf-plants-merkle-tree-certs-06 and draft-ietf-tls-trust-anchor-ids-05.
Command mtc runs a Merkle Tree Certificate CA and mirror, and verifies certificates, following draft-ietf-plants-merkle-tree-certs-06 and draft-ietf-tls-trust-anchor-ids-05.
mtc-subscriber command
Command mtc-subscriber keeps TLS servers supplied with Merkle Tree Certificates from an mtc CA.
Command mtc-subscriber keeps TLS servers supplied with Merkle Tree Certificates from an mtc CA.
internal
tlogstore
Package tlogstore stores a Merkle tree log on the local filesystem in the c2sp.org/tlog-tiles layout, so the directory can be served as is.
Package tlogstore stores a Merkle tree log on the local filesystem in the c2sp.org/tlog-tiles layout, so the directory can be served as is.
Package mirror implements a c2sp.org/tlog-mirror mirror for MTC issuance logs: it keeps a verified copy of each log, serves it as a tiled transparency log, and cosigns checkpoints and subtrees with an ML-DSA-44 MTC cosigner key, as c2sp.org/mtc-tlog requires.
Package mirror implements a c2sp.org/tlog-mirror mirror for MTC issuance logs: it keeps a verified copy of each log, serves it as a tiled transparency log, and cosigns checkpoints and subtrees with an ML-DSA-44 MTC cosigner key, as c2sp.org/mtc-tlog requires.

Jump to

Keyboard shortcuts

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