Proposed New CT Log State - Expired

192 views
Skip to first unread message

Clint Wilson

unread,
Oct 13, 2021, 6:34:33 PM10/13/21
to Certificate Transparency Policy
Hello community!

As Apple looks at its CT Log operations and its CT Log List Schema, we note that there is room for improved clarity in expressing some CT Log statuses. One such change which we’d like to make is to add an “Expired” state for CT Logs/Log Shards, used to denote when a previously Usable or Qualified Log has passed its temporal interval’s end timestamp. Since temporal intervals are enforced locally by clients, the net behavior would remain unchanged and this status would primarily ensure the log's state reflects this current behavior. In a similar way to Rejected logs, Expired logs would be trimmed from local relying party log lists.

The proposed updated schema is below. At this time, we’d like to know if this change would cause issues for ecosystem participants and whether there are any concerns with or comments on this change.

Thank you!
-Clint

{
    "type": "object",
    "required": [
        "version",
        "assetVersion",
        "operators"
    ],
    "definitions": {
        "state": {
            "type": "object",
            "properties": {
                "timestamp": {
                    "description": "The time at which the log entered this state.",
                    "examples": [
                        "2018-01-01T00:00:00Z"
                    ],
                    "format": "date-time",
                    "type": "string"
                },
                "version": {
                    "description": "The log list version in which the log entered this state.",
                    "minimum": 1,
                    "type": "string"
                }
            },
            "required": [
                "timestamp",
                "version"
            ]
        }
    },
    "properties": {
        "assetVersion": {
            "title": "Asset version containing this log list",
            "description": "Asset version in which this log list was included",
            "minimum": 1,
            "type": "number"
        },
        "version": {
            "type": "string",
            "title": "Version of this log list",
            "description": "The version will change whenever a change is made to any part of this log list.",
            "examples": [
                "1",
                "1.0.0",
                "1.0.0b"
            ]
        },
        "operators": {
            "title": "CT log operators",
            "description": "People/organizations that run Certificate Transparency logs.",
            "type": "array",
            "items": {
                "type": "object",
                "required": [
                    "name",
                    "email",
                    "logs"
                ],
                "properties": {
                    "name": {
                        "title": "Name of this log operator",
                        "type": "string"
                    },
                    "email": {
                        "title": "CT log operator email addresses",
                        "description": "The log operator can be contacted using any of these email addresses.",
                        "type": "array",
                        "minItems": 1,
                        "uniqueItems": true,
                        "items": {
                            "type": "string",
                            "format": "email"
                        }
                    },
                    "logs": {
                        "description": "Details of Certificate Transparency logs run by this operator.",
                        "type": "array",
                        "items": {
                            "type": "object",
                            "required": [
                                "key",
                                "log_id",
                                "mmd",
                                "url",
                                "state"
                            ],
                            "properties": {
                                "description": {
                                    "title": "Description of the CT log",
                                    "description": "A human-readable description that can be used to identify this log.",
                                    "type": "string"
                                },
                                "key": {
                                    "title": "The public key of the CT log",
                                    "description": "The log's public key as a DER-encoded ASN.1 SubjectPublicKeyInfo structure, then encoded as base64 (https://tools.ietf.org/html/rfc5280#section-4.1.2.7).",
                                    "type": "string"
                                },
                                "log_id": {
                                    "title": "The SHA-256 hash of the CT log's public key, base64-encoded",
                                    "description": "This is the LogID found in SCTs issued by this log (https://tools.ietf.org/html/rfc6962#section-3.2).",
                                    "type": "string",
                                    "minLength": 44,
                                    "maxLength": 44
                                },
                                "mmd": {
                                    "title": "The Maximum Merge Delay, in seconds",
                                    "description": "The CT log should not take longer than this to incorporate a certificate (https://tools.ietf.org/html/rfc6962#section-3).",
                                    "type": "number",
                                    "minimum": 1,
                                    "default": 86400
                                },
                                "url": {
                                    "title": "The base URL of the CT log's HTTP API",
                                    "description": "The API endpoints are defined in https://tools.ietf.org/html/rfc6962#section-4.",
                                    "type": "string",
                                    "format": "uri",
                                    "examples": [
                                        "https://ct.googleapis.com/pilot/"
                                    ]
                                },
                                "dns": {
                                    "title": "The domain name of the CT log's DNS API",
                                    "description": "The API endpoints are defined in https://github.com/google/certificate-transparency-rfcs/blob/master/dns/draft-ct-over-dns.md.",
                                    "type": "string",
                                    "format": "hostname",
                                    "examples": [
                                        "pilot.ct.googleapis.com"
                                    ]
                                },
                                "temporal_interval": {
                                    "description": "The log will only accept certificates that expire (have a NotAfter date) between these dates.",
                                    "type": "object",
                                    "required": [
                                        "start_inclusive",
                                        "end_exclusive"
                                    ],
                                    "properties": {
                                        "start_inclusive": {
                                            "description": "All certificates must expire on this date or later.",
                                            "type": "string",
                                            "format": "date-time",
                                            "examples": [
                                                "2018-01-01T00:00:00Z"
                                            ]
                                        },
                                        "end_exclusive": {
                                            "description": "All certificates must expire before this date.",
                                            "type": "string",
                                            "format": "date-time",
                                            "examples": [
                                                "2019-01-01T00:00:00Z"
                                            ]
                                        }
                                    }
                                },
                                "log_type": {
                                    "description": "The purpose of this log, e.g. test.",
                                    "type": "string",
                                    "enum": [
                                        "prod",
                                        "test"
                                    ]
                                },
                                "state": {
                                    "title": "The state of the log from the log list distributor's perspective.",
                                    "type": "object",
                                    "properties": {
                                        "pending": {
                                            "$ref": "#/definitions/state"
                                        },
                                        "qualified": {
                                            "$ref": "#/definitions/state"
                                        },
                                        "usable": {
                                            "$ref": "#/definitions/state"
                                        },
                                        "readonly": {
                                            "allOf": [
                                                {
                                                    "$ref": "#/definitions/state"
                                                },
                                                {
                                                    "required": [
                                                        "final_tree_head"
                                                    ],
                                                    "properties": {
                                                        "final_tree_head": {
                                                            "description": "The tree head (tree size and root hash) at which the log was made read-only.",
                                                            "type": "object",
                                                            "required": [
                                                                "tree_size",
                                                                "sha256_root_hash"
                                                            ],
                                                            "properties": {
                                                                "tree_size": {
                                                                    "type": "number",
                                                                    "minimum": 0
                                                                },
                                                                "sha256_root_hash": {
                                                                    "type": "string",
                                                                    "minLength": 44,
                                                                    "maxLength": 44
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            ]
                                        },
                                        "retired": {
                                            "$ref": "#/definitions/state"
                                        },
                                        "rejected": {
                                            "$ref": "#/definitions/state"
                                        },     
                                        "expired": {
                                            "$ref": "#/definitions/state"
                                        }
                                    },
                                    "oneOf": [
                                        {
                                            "required": [
                                                "pending"
                                            ]
                                        },
                                        {
                                            "required": [
                                                "qualified"
                                            ]
                                        },
                                        {
                                            "required": [
                                                "usable"
                                            ]
                                        },
                                        {
                                            "required": [
                                                "readonly"
                                            ]
                                        },
                                        {
                                            "required": [
                                                "retired"
                                            ]
                                        },
                                        {
                                            "required": [
                                                "rejected"
                                            ]
                                        },
                                        {
                                            "required": [
                                                "expired"
                                            ]
                                        }
                                    ]
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

Aaron Gable

unread,
Oct 19, 2021, 4:04:29 PM10/19/21
to Clint Wilson, Certificate Transparency Policy
As a comparative newcomer to this space: what is the semantic meaning of "retired"? Is the issue here that "retired" includes both logs which are no longer used due to operational failures and logs which are no longer used due to temporal sharding, and there is a desire to separate those two categories?

--
You received this message because you are subscribed to the Google Groups "Certificate Transparency Policy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ct-policy+...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/ct-policy/973E1048-A12B-482A-8326-E3C1D5396420%40apple.com.

Devon O'Brien

unread,
Oct 19, 2021, 4:41:21 PM10/19/21
to Certificate Transparency Policy, aa...@letsencrypt.org, Certificate Transparency Policy, Clint
Regarding Aaron's question, we (Chrome) maintain a doc that describes the set of possible CT Log states as well as how these states map to CT Policy and technical CT enforcement. I'll leave it to Clint to confirm whether these definitions match Apple's, but historically we've treated them very similarly, if not the same. As always, if there is anything that is unclear or ambiguous, we're open to suggestions that increase clarity and readability.

Regarding the proposed Expired state, our (Chrome's) stance is that there is not a material difference between Expired and Rejected in terms of either technical CT enforcement or compliance with CT Policy. This is the reason that we cull all sharded CT Logs from https://www.gstatic.com/ct/log_list/v2/log_list.json a couple releases after these logs expire (but keep them around in https://www.gstatic.com/ct/log_list/v2/all_logs_list.json in perpetuity as an informative reference).

Apple is in a slightly different situation in that they currently maintain all logs that have ever been Qualified in https://valid.apple.com/ct/log_list/current_log_list.json, and it is more challenging for an outside observer to understand which logs are still relevant. Alternative approaches could be maintaining historical information in a separate log list, or publishing and maintaining a KB article that doesn't need to abide by the log list schema for logs that are no longer relied upon by macOS, iOS and friends.
 
Each new state adds to the complexity of the CT Log state machine I linked above, and for what it's worth, Chrome is not likely to incorporate a new Expired state into its schema since our primary interest in publishing these lists is to communicate information about active CT Logs whose SCTs impact certificate validation. That said, I'm interested whether other members of the CT community feel there is value in adding a new state for expired CT Logs to differentiate from those removed for a non-expiry reason.

-Devon

Andrew Ayer

unread,
Oct 21, 2021, 8:08:47 PM10/21/21
to Clint Wilson, 'Clint Wilson' via Certificate Transparency Policy
Right now, every log state means something different to at least one
type of ecosystem participant (UA, CA, monitor). But as far as I can
tell, all ecosystem participants would treat Rejected and Expired
exactly the same. I think it's already challenging enough to
understand the nuances between all the log states (especially retired vs
rejected) and adding a new log state that's functionally equivalent to
an existing log state would only muddy the waters. But I'd be
interested in hearing if any ecosystem participants would treat Expired
differently from Rejected.

Just spitballing an alternative: the "rejected" object could contain an
optional freeform string field that contains the reason for the log's
removal.

Regards,
Andrew

On Wed, 13 Oct 2021 15:34:30 -0700
"'Clint Wilson' via Certificate Transparency Policy"
<ct-p...@chromium.org> wrote:

Reply all
Reply to author
Forward
0 new messages