...

Source file src/github.com/letsencrypt/boulder/linter/lints/common.go

Documentation: github.com/letsencrypt/boulder/linter/lints

     1  package lints
     2  
     3  import (
     4  	"bytes"
     5  	"net/url"
     6  	"time"
     7  
     8  	"github.com/zmap/zcrypto/encoding/asn1"
     9  	"github.com/zmap/zcrypto/x509/pkix"
    10  	"github.com/zmap/zlint/v3/lint"
    11  	"golang.org/x/crypto/cryptobyte"
    12  	cryptobyte_asn1 "golang.org/x/crypto/cryptobyte/asn1"
    13  )
    14  
    15  const (
    16  	// CABF Baseline Requirements 6.3.2 Certificate operational periods:
    17  	// For the purpose of calculations, a day is measured as 86,400 seconds.
    18  	// Any amount of time greater than this, including fractional seconds and/or
    19  	// leap seconds, shall represent an additional day.
    20  	BRDay time.Duration = 86400 * time.Second
    21  
    22  	// Declare our own Sources for use in zlint registry filtering.
    23  	LetsEncryptCPS lint.LintSource = "LECPS"
    24  	ChromeCTPolicy lint.LintSource = "ChromeCT"
    25  )
    26  
    27  var (
    28  	CPSV33Date           = time.Date(2021, time.June, 8, 0, 0, 0, 0, time.UTC)
    29  	MozillaPolicy281Date = time.Date(2023, time.February, 15, 0, 0, 0, 0, time.UTC)
    30  )
    31  
    32  /*
    33  	 IssuingDistributionPoint stores the IA5STRING value of the optional
    34  	 distribution point, and the (implied OPTIONAL) BOOLEAN values of
    35  	 onlyContainsUserCerts and onlyContainsCACerts.
    36  
    37  			RFC 5280
    38  			* Section 5.2.5
    39  				IssuingDistributionPoint ::= SEQUENCE {
    40  					distributionPoint          [0] DistributionPointName OPTIONAL,
    41  					onlyContainsUserCerts      [1] BOOLEAN DEFAULT FALSE,
    42  					onlyContainsCACerts        [2] BOOLEAN DEFAULT FALSE,
    43  					...
    44  				}
    45  
    46  			* Section 4.2.1.13
    47  				DistributionPointName ::= CHOICE {
    48  					fullName                [0]     GeneralNames,
    49  					... }
    50  
    51  			* Appendix A.1, Page 128
    52  				GeneralName ::= CHOICE {
    53  					...
    54  			        uniformResourceIdentifier [6]  IA5String,
    55  					... }
    56  */
    57  type IssuingDistributionPoint struct {
    58  	DistributionPointURI  *url.URL
    59  	OnlyContainsUserCerts bool
    60  	OnlyContainsCACerts   bool
    61  }
    62  
    63  // NewIssuingDistributionPoint is a constructor which returns an
    64  // IssuingDistributionPoint with each field set to zero values.
    65  func NewIssuingDistributionPoint() *IssuingDistributionPoint {
    66  	return &IssuingDistributionPoint{}
    67  }
    68  
    69  // GetExtWithOID is a helper for several of our custom lints. It returns the
    70  // extension with the given OID if it exists, or nil otherwise.
    71  func GetExtWithOID(exts []pkix.Extension, oid asn1.ObjectIdentifier) *pkix.Extension {
    72  	for _, ext := range exts {
    73  		if ext.Id.Equal(oid) {
    74  			return &ext
    75  		}
    76  	}
    77  	return nil
    78  }
    79  
    80  // ReadOptionalASN1BooleanWithTag attempts to read and advance incoming to
    81  // search for an optional DER-encoded ASN.1 element tagged with the given tag.
    82  // Unless out is nil, it stores whether an element with the tag was found in
    83  // out, otherwise out will take the default value. It reports whether all reads
    84  // were successful.
    85  func ReadOptionalASN1BooleanWithTag(incoming *cryptobyte.String, out *bool, tag cryptobyte_asn1.Tag, defaultValue bool) bool {
    86  	// ReadOptionalASN1 performs a peek and will not advance if the tag is
    87  	// missing, meaning that incoming will retain bytes.
    88  	var valuePresent bool
    89  	var valueBytes cryptobyte.String
    90  	if !incoming.ReadOptionalASN1(&valueBytes, &valuePresent, tag) {
    91  		return false
    92  	}
    93  	val := defaultValue
    94  	if valuePresent {
    95  		/*
    96  			X.690 (07/2002)
    97  			https://www.itu.int/rec/T-REC-X.690-200207-S/en
    98  
    99  			Section 8.2.2:
   100  				If the boolean value is:
   101  				FALSE
   102  				the octet shall be zero.
   103  				If the boolean value is
   104  				TRUE
   105  				the octet shall have any non-zero value, as a sender's option.
   106  
   107  			Section 11.1 Boolean values:
   108  				If the encoding represents the boolean value TRUE, its single contents octet shall have all eight
   109  				bits set to one. (Contrast with 8.2.2.)
   110  
   111  			Succinctly, BER encoding states any nonzero value is TRUE. The DER
   112  			encoding restricts the value 0xFF as TRUE and any other: 0x01,
   113  			0x23, 0xFE, etc as invalid encoding.
   114  		*/
   115  		boolBytes := []byte(valueBytes)
   116  		if bytes.Equal(boolBytes, []byte{0xFF}) {
   117  			val = true
   118  		} else if bytes.Equal(boolBytes, []byte{0x00}) {
   119  			val = false
   120  		} else {
   121  			// Unrecognized DER encoding of boolean!
   122  			return false
   123  		}
   124  	}
   125  	if out != nil {
   126  		*out = val
   127  	}
   128  
   129  	// All reads were successful.
   130  	return true
   131  }
   132  

View as plain text