github.com/twelsh-aw/go/src@v0.0.0-20230516233729-a56fe86a7c81/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 "fmt" 11 ) 12 13 func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) { 14 certs := macOS.CFArrayCreateMutable() 15 defer macOS.ReleaseCFArray(certs) 16 leaf, err := macOS.SecCertificateCreateWithData(c.Raw) 17 if err != nil { 18 return nil, errors.New("invalid leaf certificate") 19 } 20 macOS.CFArrayAppendValue(certs, leaf) 21 if opts.Intermediates != nil { 22 for _, lc := range opts.Intermediates.lazyCerts { 23 c, err := lc.getCert() 24 if err != nil { 25 return nil, err 26 } 27 sc, err := macOS.SecCertificateCreateWithData(c.Raw) 28 if err != nil { 29 return nil, err 30 } 31 macOS.CFArrayAppendValue(certs, sc) 32 } 33 } 34 35 policies := macOS.CFArrayCreateMutable() 36 defer macOS.ReleaseCFArray(policies) 37 sslPolicy, err := macOS.SecPolicyCreateSSL(opts.DNSName) 38 if err != nil { 39 return nil, err 40 } 41 macOS.CFArrayAppendValue(policies, sslPolicy) 42 43 trustObj, err := macOS.SecTrustCreateWithCertificates(certs, policies) 44 if err != nil { 45 return nil, err 46 } 47 defer macOS.CFRelease(trustObj) 48 49 if !opts.CurrentTime.IsZero() { 50 dateRef := macOS.TimeToCFDateRef(opts.CurrentTime) 51 defer macOS.CFRelease(dateRef) 52 if err := macOS.SecTrustSetVerifyDate(trustObj, dateRef); err != nil { 53 return nil, err 54 } 55 } 56 57 // TODO(roland): we may want to allow passing in SCTs via VerifyOptions and 58 // set them via SecTrustSetSignedCertificateTimestamps, since Apple will 59 // always enforce its SCT requirements, and there are still _some_ people 60 // using TLS or OCSP for that. 61 62 if ret, err := macOS.SecTrustEvaluateWithError(trustObj); err != nil { 63 switch ret { 64 case macOS.ErrSecCertificateExpired: 65 return nil, CertificateInvalidError{c, Expired, err.Error()} 66 case macOS.ErrSecHostNameMismatch: 67 return nil, HostnameError{c, opts.DNSName} 68 case macOS.ErrSecNotTrusted: 69 return nil, UnknownAuthorityError{Cert: c} 70 default: 71 return nil, fmt.Errorf("x509: %s", err) 72 } 73 } 74 75 chain := [][]*Certificate{{}} 76 numCerts := macOS.SecTrustGetCertificateCount(trustObj) 77 for i := 0; i < numCerts; i++ { 78 certRef, err := macOS.SecTrustGetCertificateAtIndex(trustObj, i) 79 if err != nil { 80 return nil, err 81 } 82 cert, err := exportCertificate(certRef) 83 if err != nil { 84 return nil, err 85 } 86 chain[0] = append(chain[0], cert) 87 } 88 if len(chain[0]) == 0 { 89 // This should _never_ happen, but to be safe 90 return nil, errors.New("x509: macOS certificate verification internal error") 91 } 92 93 if opts.DNSName != "" { 94 // If we have a DNS name, apply our own name verification 95 if err := chain[0][0].VerifyHostname(opts.DNSName); err != nil { 96 return nil, err 97 } 98 } 99 100 keyUsages := opts.KeyUsages 101 if len(keyUsages) == 0 { 102 keyUsages = []ExtKeyUsage{ExtKeyUsageServerAuth} 103 } 104 105 // If any key usage is acceptable then we're done. 106 for _, usage := range keyUsages { 107 if usage == ExtKeyUsageAny { 108 return chain, nil 109 } 110 } 111 112 if !checkChainForKeyUsage(chain[0], keyUsages) { 113 return nil, CertificateInvalidError{c, IncompatibleUsage, ""} 114 } 115 116 return chain, nil 117 } 118 119 // exportCertificate returns a *Certificate for a SecCertificateRef. 120 func exportCertificate(cert macOS.CFRef) (*Certificate, error) { 121 data, err := macOS.SecCertificateCopyData(cert) 122 if err != nil { 123 return nil, err 124 } 125 return ParseCertificate(data) 126 } 127 128 func loadSystemRoots() (*CertPool, error) { 129 return &CertPool{systemPool: true}, nil 130 }