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