Source file src/crypto/x509/root_darwin.go

     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 := macOS.SecCertificateCreateWithData(c.Raw)
    16  	if leaf == 0 {
    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 := macOS.SecCertificateCreateWithData(c.Raw)
    27  			if sc != 0 {
    28  				macOS.CFArrayAppendValue(certs, sc)
    29  			}
    30  		}
    31  	}
    32  
    33  	policies := macOS.CFArrayCreateMutable()
    34  	defer macOS.ReleaseCFArray(policies)
    35  	sslPolicy := macOS.SecPolicyCreateSSL(opts.DNSName)
    36  	macOS.CFArrayAppendValue(policies, sslPolicy)
    37  
    38  	trustObj, err := macOS.SecTrustCreateWithCertificates(certs, policies)
    39  	if err != nil {
    40  		return nil, err
    41  	}
    42  	defer macOS.CFRelease(trustObj)
    43  
    44  	if !opts.CurrentTime.IsZero() {
    45  		dateRef := macOS.TimeToCFDateRef(opts.CurrentTime)
    46  		defer macOS.CFRelease(dateRef)
    47  		if err := macOS.SecTrustSetVerifyDate(trustObj, dateRef); err != nil {
    48  			return nil, err
    49  		}
    50  	}
    51  
    52  	// TODO(roland): we may want to allow passing in SCTs via VerifyOptions and
    53  	// set them via SecTrustSetSignedCertificateTimestamps, since Apple will
    54  	// always enforce its SCT requirements, and there are still _some_ people
    55  	// using TLS or OCSP for that.
    56  
    57  	if err := macOS.SecTrustEvaluateWithError(trustObj); err != nil {
    58  		return nil, err
    59  	}
    60  
    61  	chain := [][]*Certificate{{}}
    62  	numCerts := macOS.SecTrustGetCertificateCount(trustObj)
    63  	for i := 0; i < numCerts; i++ {
    64  		certRef := macOS.SecTrustGetCertificateAtIndex(trustObj, i)
    65  		cert, err := exportCertificate(certRef)
    66  		if err != nil {
    67  			return nil, err
    68  		}
    69  		chain[0] = append(chain[0], cert)
    70  	}
    71  	if len(chain[0]) == 0 {
    72  		// This should _never_ happen, but to be safe
    73  		return nil, errors.New("x509: macOS certificate verification internal error")
    74  	}
    75  
    76  	if opts.DNSName != "" {
    77  		// If we have a DNS name, apply our own name verification
    78  		if err := chain[0][0].VerifyHostname(opts.DNSName); err != nil {
    79  			return nil, err
    80  		}
    81  	}
    82  
    83  	keyUsages := opts.KeyUsages
    84  	if len(keyUsages) == 0 {
    85  		keyUsages = []ExtKeyUsage{ExtKeyUsageServerAuth}
    86  	}
    87  
    88  	// If any key usage is acceptable then we're done.
    89  	for _, usage := range keyUsages {
    90  		if usage == ExtKeyUsageAny {
    91  			return chain, nil
    92  		}
    93  	}
    94  
    95  	if !checkChainForKeyUsage(chain[0], keyUsages) {
    96  		return nil, CertificateInvalidError{c, IncompatibleUsage, ""}
    97  	}
    98  
    99  	return chain, nil
   100  }
   101  
   102  // exportCertificate returns a *Certificate for a SecCertificateRef.
   103  func exportCertificate(cert macOS.CFRef) (*Certificate, error) {
   104  	data, err := macOS.SecCertificateCopyData(cert)
   105  	if err != nil {
   106  		return nil, err
   107  	}
   108  	return ParseCertificate(data)
   109  }
   110  
   111  func loadSystemRoots() (*CertPool, error) {
   112  	return &CertPool{systemPool: true}, nil
   113  }
   114  

View as plain text