github.com/mtsmfm/go/src@v0.0.0-20221020090648-44bdcb9f8fde/crypto/x509/root_darwin.go (about)

     1  // Copyright 2020 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package x509
     6  
     7  import (
     8  	macOS "crypto/x509/internal/macos"
     9  	"errors"
    10  )
    11  
    12  func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
    13  	certs := macOS.CFArrayCreateMutable()
    14  	defer macOS.ReleaseCFArray(certs)
    15  	leaf, err := macOS.SecCertificateCreateWithData(c.Raw)
    16  	if err != nil {
    17  		return nil, errors.New("invalid leaf certificate")
    18  	}
    19  	macOS.CFArrayAppendValue(certs, leaf)
    20  	if opts.Intermediates != nil {
    21  		for _, lc := range opts.Intermediates.lazyCerts {
    22  			c, err := lc.getCert()
    23  			if err != nil {
    24  				return nil, err
    25  			}
    26  			sc, err := macOS.SecCertificateCreateWithData(c.Raw)
    27  			if err == nil {
    28  				macOS.CFArrayAppendValue(certs, sc)
    29  			}
    30  		}
    31  	}
    32  
    33  	policies := macOS.CFArrayCreateMutable()
    34  	defer macOS.ReleaseCFArray(policies)
    35  	sslPolicy, err := macOS.SecPolicyCreateSSL(opts.DNSName)
    36  	if err != nil {
    37  		return nil, err
    38  	}
    39  	macOS.CFArrayAppendValue(policies, sslPolicy)
    40  
    41  	trustObj, err := macOS.SecTrustCreateWithCertificates(certs, policies)
    42  	if err != nil {
    43  		return nil, err
    44  	}
    45  	defer macOS.CFRelease(trustObj)
    46  
    47  	if !opts.CurrentTime.IsZero() {
    48  		dateRef := macOS.TimeToCFDateRef(opts.CurrentTime)
    49  		defer macOS.CFRelease(dateRef)
    50  		if err := macOS.SecTrustSetVerifyDate(trustObj, dateRef); err != nil {
    51  			return nil, err
    52  		}
    53  	}
    54  
    55  	// TODO(roland): we may want to allow passing in SCTs via VerifyOptions and
    56  	// set them via SecTrustSetSignedCertificateTimestamps, since Apple will
    57  	// always enforce its SCT requirements, and there are still _some_ people
    58  	// using TLS or OCSP for that.
    59  
    60  	if err := macOS.SecTrustEvaluateWithError(trustObj); err != nil {
    61  		return nil, err
    62  	}
    63  
    64  	chain := [][]*Certificate{{}}
    65  	numCerts := macOS.SecTrustGetCertificateCount(trustObj)
    66  	for i := 0; i < numCerts; i++ {
    67  		certRef, err := macOS.SecTrustGetCertificateAtIndex(trustObj, i)
    68  		if err != nil {
    69  			return nil, err
    70  		}
    71  		cert, err := exportCertificate(certRef)
    72  		if err != nil {
    73  			return nil, err
    74  		}
    75  		chain[0] = append(chain[0], cert)
    76  	}
    77  	if len(chain[0]) == 0 {
    78  		// This should _never_ happen, but to be safe
    79  		return nil, errors.New("x509: macOS certificate verification internal error")
    80  	}
    81  
    82  	if opts.DNSName != "" {
    83  		// If we have a DNS name, apply our own name verification
    84  		if err := chain[0][0].VerifyHostname(opts.DNSName); err != nil {
    85  			return nil, err
    86  		}
    87  	}
    88  
    89  	keyUsages := opts.KeyUsages
    90  	if len(keyUsages) == 0 {
    91  		keyUsages = []ExtKeyUsage{ExtKeyUsageServerAuth}
    92  	}
    93  
    94  	// If any key usage is acceptable then we're done.
    95  	for _, usage := range keyUsages {
    96  		if usage == ExtKeyUsageAny {
    97  			return chain, nil
    98  		}
    99  	}
   100  
   101  	if !checkChainForKeyUsage(chain[0], keyUsages) {
   102  		return nil, CertificateInvalidError{c, IncompatibleUsage, ""}
   103  	}
   104  
   105  	return chain, nil
   106  }
   107  
   108  // exportCertificate returns a *Certificate for a SecCertificateRef.
   109  func exportCertificate(cert macOS.CFRef) (*Certificate, error) {
   110  	data, err := macOS.SecCertificateCopyData(cert)
   111  	if err != nil {
   112  		return nil, err
   113  	}
   114  	return ParseCertificate(data)
   115  }
   116  
   117  func loadSystemRoots() (*CertPool, error) {
   118  	return &CertPool{systemPool: true}, nil
   119  }