lints/lint_ct_sct_policy_count_unsatisfied.go
func (l *sctPolicyCount) Execute(c *x509.Certificate) *LintResult {
	// Determine the required number of SCTs from separate logs
	expected := appleCTPolicyExpectedSCTs(c)

	// If there are no SCTs then the job is easy. We can return a Notice
	// LintResult immediately.
	if len(c.SignedCertificateTimestampList) == 0 && expected > 0 {
		return &LintResult{
			Status: Notice,
			Details: fmt.Sprintf(
				"Certificate had 0 embedded SCTs. Browser policy may require %d for this certificate.",
				expected),
		}
	}

	// Build a map from LogID to SCT so that we can count embedded SCTs by unique
	// log.
	sctsByLogID := make(map[ct.SHA256Hash]*ct.SignedCertificateTimestamp)
	for _, sct := range c.SignedCertificateTimestampList {
		sctsByLogID[sct.LogID] = sct
	}

	// If the number of embedded SCTs from separate logs meets expected return
	// a Pass result.
	if len(sctsByLogID) >= expected {
		return &LintResult{Status: Pass}
	}

	// Otherwise return a Notice result - there weren't enough SCTs embedded in
	// the certificate. More must be provided by OCSP stapling if the certificate
	// is to meet Apple's CT policy.
	return &LintResult{
		Status: Notice,
		Details: fmt.Sprintf(
			"Certificate had %d embedded SCTs from distinct log IDs. "+
				"Browser policy may require %d for this certificate.",
			len(sctsByLogID), expected),
	}
}
func (l *sctPolicyCount) Execute(c *x509.Certificate) *LintResult {
	// Determine the required number of SCTs from separate logs
	expected := appleCTPolicyExpectedSCTs(c)

	// If there are no SCTs then the job is easy. We can return a Notice
	// LintResult immediately.
	if len(c.SignedCertificateTimestampList) == 0 && expected > 0 {
		return &LintResult{
			Status: Notice,
			Details: fmt.Sprintf(
				"Certificate had 0 embedded SCTs. Browser policy may require %d for this certificate.",
				expected),
		}
	}

	// Build a map from LogID to SCT so that we can count embedded SCTs by unique
	// log.
	sctsByLogID := make(map[ct.SHA256Hash]*ct.SignedCertificateTimestamp)
	for _, sct := range c.SignedCertificateTimestampList {
		sctsByLogID[sct.LogID] = sct
	}

	// If the number of embedded SCTs from separate logs meets expected return
	// a Pass result.
	if len(sctsByLogID) >= expected {
		return &LintResult{Status: Pass}
	}

	// Otherwise return a Notice result - there weren't enough SCTs embedded in
	// the certificate. More must be provided by OCSP stapling if the certificate
	// is to meet Apple's CT policy.
	return &LintResult{
		Status: Notice,
		Details: fmt.Sprintf(
			"Certificate had %d embedded SCTs from distinct log IDs. "+
				"Browser policy may require %d for this certificate.",
			len(sctsByLogID), expected),
	}
}
func ( l * sctPolicyCount ) Execute ( c * x509 . Certificate ) * LintResult { // Determine the required number of SCTs from separate logs expected := appleCTPolicyExpectedSCTs ( c ) // If there are no SCTs then the job is easy. We can return a Notice // LintResult immediately. if len ( c . SignedCertificateTimestampList ) == 0 && expected > 0 { return & LintResult { Status : Notice , Details : fmt . Sprintf ( " " , expected ) , } } // Build a map from LogID to SCT so that we can count embedded SCTs by unique // log. sctsByLogID := make ( map [ ct . SHA256Hash ] * ct . SignedCertificateTimestamp ) for _ , sct := range c . SignedCertificateTimestampList { sctsByLogID [ sct . LogID ] = sct } // If the number of embedded SCTs from separate logs meets expected return // a Pass result. if len ( sctsByLogID ) >= expected { return & LintResult { Status : Pass } } // Otherwise return a Notice result - there weren't enough SCTs embedded in // the certificate. More must be provided by OCSP stapling if the certificate // is to meet Apple's CT policy. return & LintResult { Status : Notice , Details : fmt . Sprintf ( " " + " " , len ( sctsByLogID ) , expected ) , } }
// Execute checks if the provided certificate has embedded SCTs from
// a sufficient number of unique CT logs to meet Apple's CT log policy[0],
// effective Oct 15th, 2018.
//
// The number of required SCTs from different logs is calculated based on the
// Certificate's lifetime. If the number of required SCTs are not embedded in
// the certificate a Notice level LintResult is returned.
//
// | Certificate lifetime | # of SCTs from separate logs |
// -------------------------------------------------------
// | Less than 15 months  | 2                            |
// | 15 to 27 months      | 3                            |
// | 27 to 39 months      | 4                            |
// | More than 39 months  | 5                            |
// -------------------------------------------------------
//
// Important note 1: We can't know whether additional SCTs were presented
// alongside the certificate via OCSP stapling. This linter assumes only
// embedded SCTs are used and ignores the portion of the Apple policy related to
// SCTs delivered via OCSP. This is one limitation that restricts the linter's
// findings to Notice level. See more background discussion in Issue 226[1].
//
// Important note 2: The linter doesn't maintain a list of Apple's trusted
// logs. The SCTs embedded in the certificate may not be from log's Apple
// actually trusts. Similarly the embedded SCT signatures are not validated
// in any way.
//
// [0]: https://support.apple.com/en-us/HT205280
// [1]: https://github.com/zmap/zlint/issues/226
Execute checks if the provided certificate has embedded SCTs from a sufficient number of unique CT logs to meet Apple s CT log policy [ 0 ] effective Oct 15th 2018 . The number of required SCTs from different logs is calculated based on the Certificate s lifetime . If the number of required SCTs are not embedded in the certificate a Notice level LintResult is returned . | Certificate lifetime | # of SCTs from separate logs | ------------------------------------------------------- | Less than 15 months | 2 | | 15 to 27 months | 3 | | 27 to 39 months | 4 | | More than 39 months | 5 | ------------------------------------------------------- Important note 1 : We can t know whether additional SCTs were presented alongside the certificate via OCSP stapling . This linter assumes only embedded SCTs are used and ignores the portion of the Apple policy related to SCTs delivered via OCSP . This is one limitation that restricts the linter s findings to Notice level . See more background discussion in Issue 226 [ 1 ] . Important note 2 : The linter doesn t maintain a list of Apple s trusted logs . The SCTs embedded in the certificate may not be from log s Apple actually trusts . Similarly the embedded SCT signatures are not validated in any way . [ 0 ] : https : // support . apple . com / en - us / HT205280 [ 1 ] : https : // github . com / zmap / zlint / issues / 226