Source file src/pkg/crypto/x509/root_darwin_arm_gen.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package main
18
19 import (
20 "bytes"
21 "crypto/sha256"
22 "crypto/x509"
23 "encoding/hex"
24 "encoding/pem"
25 "flag"
26 "fmt"
27 "go/format"
28 "io/ioutil"
29 "log"
30 "net/http"
31 "os/exec"
32 "regexp"
33 "strings"
34 )
35
36 var output = flag.String("output", "root_darwin_armx.go", "file name to write")
37
38 func main() {
39 certs, err := selectCerts()
40 if err != nil {
41 log.Fatal(err)
42 }
43
44 buf := new(bytes.Buffer)
45
46 fmt.Fprintf(buf, "// Code generated by root_darwin_arm_gen --output %s; DO NOT EDIT.\n", *output)
47 fmt.Fprintf(buf, "%s", header)
48
49 fmt.Fprintf(buf, "const systemRootsPEM = `\n")
50 for _, cert := range certs {
51 b := &pem.Block{
52 Type: "CERTIFICATE",
53 Bytes: cert.Raw,
54 }
55 if err := pem.Encode(buf, b); err != nil {
56 log.Fatal(err)
57 }
58 }
59 fmt.Fprintf(buf, "`")
60
61 source, err := format.Source(buf.Bytes())
62 if err != nil {
63 log.Fatal("source format error:", err)
64 }
65 if err := ioutil.WriteFile(*output, source, 0644); err != nil {
66 log.Fatal(err)
67 }
68 }
69
70 func selectCerts() ([]*x509.Certificate, error) {
71 ids, err := fetchCertIDs()
72 if err != nil {
73 return nil, err
74 }
75
76 scerts, err := sysCerts()
77 if err != nil {
78 return nil, err
79 }
80
81 var certs []*x509.Certificate
82 for _, id := range ids {
83 if c, ok := scerts[id.fingerprint]; ok {
84 certs = append(certs, c)
85 } else {
86 fmt.Printf("WARNING: cannot find certificate: %s (fingerprint: %s)\n", id.name, id.fingerprint)
87 }
88 }
89 return certs, nil
90 }
91
92 func sysCerts() (certs map[string]*x509.Certificate, err error) {
93 cmd := exec.Command("/usr/bin/security", "find-certificate", "-a", "-p", "/System/Library/Keychains/SystemRootCertificates.keychain")
94 data, err := cmd.Output()
95 if err != nil {
96 return nil, err
97 }
98 certs = make(map[string]*x509.Certificate)
99 for len(data) > 0 {
100 var block *pem.Block
101 block, data = pem.Decode(data)
102 if block == nil {
103 break
104 }
105 if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
106 continue
107 }
108
109 cert, err := x509.ParseCertificate(block.Bytes)
110 if err != nil {
111 continue
112 }
113
114 fingerprint := sha256.Sum256(cert.Raw)
115 certs[hex.EncodeToString(fingerprint[:])] = cert
116 }
117 return certs, nil
118 }
119
120 type certID struct {
121 name string
122 fingerprint string
123 }
124
125
126 func fetchCertIDs() ([]certID, error) {
127
128
129 resp, err := http.Get("https://support.apple.com/en-us/HT208125")
130 if err != nil {
131 return nil, err
132 }
133 defer resp.Body.Close()
134 body, err := ioutil.ReadAll(resp.Body)
135 if err != nil {
136 return nil, err
137 }
138 text := string(body)
139 text = text[strings.Index(text, "<div id=trusted"):]
140 text = text[:strings.Index(text, "</div>")]
141
142 var ids []certID
143 cols := make(map[string]int)
144 for i, rowmatch := range regexp.MustCompile("(?s)<tr>(.*?)</tr>").FindAllStringSubmatch(text, -1) {
145 row := rowmatch[1]
146 if i == 0 {
147
148 for i, match := range regexp.MustCompile("(?s)<th>(.*?)</th>").FindAllStringSubmatch(row, -1) {
149 cols[match[1]] = i
150 }
151 continue
152 }
153
154 values := regexp.MustCompile("(?s)<td>(.*?)</td>").FindAllStringSubmatch(row, -1)
155 name := values[cols["Certificate name"]][1]
156 fingerprint := values[cols["Fingerprint (SHA-256)"]][1]
157 fingerprint = strings.ReplaceAll(fingerprint, "<br>", "")
158 fingerprint = strings.ReplaceAll(fingerprint, "\n", "")
159 fingerprint = strings.ReplaceAll(fingerprint, " ", "")
160 fingerprint = strings.ToLower(fingerprint)
161
162 ids = append(ids, certID{
163 name: name,
164 fingerprint: fingerprint,
165 })
166 }
167 return ids, nil
168 }
169
170 const header = `
171 // Copyright 2015 The Go Authors. All rights reserved.
172 // Use of this source code is governed by a BSD-style
173 // license that can be found in the LICENSE file.
174
175 // +build cgo
176 // +build darwin
177 // +build arm arm64 ios
178
179 package x509
180
181 func loadSystemRoots() (*CertPool, error) {
182 p := NewCertPool()
183 p.AppendCertsFromPEM([]byte(systemRootsPEM))
184 return p, nil
185 }
186 `
187
View as plain text