Source file
src/crypto/x509/root_ios_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 "archive/tar"
21 "bytes"
22 "compress/gzip"
23 "crypto/sha256"
24 "crypto/tls"
25 "crypto/x509"
26 "encoding/pem"
27 "flag"
28 "fmt"
29 "go/format"
30 "io"
31 "log"
32 "net/http"
33 "os"
34 "path"
35 "sort"
36 "strings"
37 "time"
38 )
39
40 func main() {
41 var output = flag.String("output", "root_ios.go", "file name to write")
42 var version = flag.String("version", "", "security_certificates version")
43 flag.Parse()
44 if *version == "" {
45 log.Fatal("Select the latest security_certificates version from " +
46 "https://opensource.apple.com/source/security_certificates/")
47 }
48
49 url := "https://opensource.apple.com/tarballs/security_certificates/security_certificates-%s.tar.gz"
50 hc := &http.Client{Timeout: 1 * time.Minute}
51 resp, err := hc.Get(fmt.Sprintf(url, *version))
52 if err != nil {
53 log.Fatal(err)
54 }
55 defer resp.Body.Close()
56 if resp.StatusCode != http.StatusOK {
57 log.Fatalf("HTTP status not OK: %s", resp.Status)
58 }
59
60 zr, err := gzip.NewReader(resp.Body)
61 if err != nil {
62 log.Fatal(err)
63 }
64 defer zr.Close()
65
66 var certs []*x509.Certificate
67 pool := x509.NewCertPool()
68
69 tr := tar.NewReader(zr)
70 for {
71 hdr, err := tr.Next()
72 if err == io.EOF {
73 break
74 }
75 if err != nil {
76 log.Fatal(err)
77 }
78
79 rootsDirectory := fmt.Sprintf("security_certificates-%s/certificates/roots/", *version)
80 if dir, file := path.Split(hdr.Name); hdr.Typeflag != tar.TypeReg ||
81 dir != rootsDirectory || strings.HasPrefix(file, ".") {
82 continue
83 }
84
85 der, err := io.ReadAll(tr)
86 if err != nil {
87 log.Fatal(err)
88 }
89
90 c, err := x509.ParseCertificate(der)
91 if err != nil {
92 log.Printf("Failed to parse certificate %q: %v", hdr.Name, err)
93 continue
94 }
95
96 certs = append(certs, c)
97 pool.AddCert(c)
98 }
99
100
101
102 for _, c := range certs {
103 if c.Subject.CommonName == "Symantec Class 2 Public Primary Certification Authority - G4" {
104 log.Fatal("The pool includes a removed root!")
105 }
106 }
107 conn, err := tls.Dial("tcp", "mail.google.com:443", &tls.Config{
108 RootCAs: pool,
109 })
110 if err != nil {
111 log.Fatal(err)
112 }
113 conn.Close()
114
115 certName := func(c *x509.Certificate) string {
116 if c.Subject.CommonName != "" {
117 return c.Subject.CommonName
118 }
119 if len(c.Subject.OrganizationalUnit) > 0 {
120 return c.Subject.OrganizationalUnit[0]
121 }
122 return c.Subject.Organization[0]
123 }
124 sort.Slice(certs, func(i, j int) bool {
125 if strings.ToLower(certName(certs[i])) != strings.ToLower(certName(certs[j])) {
126 return strings.ToLower(certName(certs[i])) < strings.ToLower(certName(certs[j]))
127 }
128 if !certs[i].NotBefore.Equal(certs[j].NotBefore) {
129 return certs[i].NotBefore.Before(certs[j].NotBefore)
130 }
131 fi, fj := sha256.Sum256(certs[i].Raw), sha256.Sum256(certs[j].Raw)
132 return bytes.Compare(fi[:], fj[:]) < 0
133 })
134
135 out := new(bytes.Buffer)
136 fmt.Fprintf(out, header, *version)
137 fmt.Fprintf(out, "const systemRootsPEM = `\n")
138
139 for _, c := range certs {
140 fmt.Fprintf(out, "# %q\n", certName(c))
141 h := sha256.Sum256(c.Raw)
142 fmt.Fprintf(out, "# % X\n", h[:len(h)/2])
143 fmt.Fprintf(out, "# % X\n", h[len(h)/2:])
144 b := &pem.Block{
145 Type: "CERTIFICATE",
146 Bytes: c.Raw,
147 }
148 if err := pem.Encode(out, b); err != nil {
149 log.Fatal(err)
150 }
151 }
152
153 fmt.Fprintf(out, "`")
154
155 source, err := format.Source(out.Bytes())
156 if err != nil {
157 log.Fatal(err)
158 }
159 if err := os.WriteFile(*output, source, 0644); err != nil {
160 log.Fatal(err)
161 }
162 }
163
164 const header = `// Code generated by root_ios_gen.go -version %s; DO NOT EDIT.
165 // Update the version in root.go and regenerate with "go generate".
166
167 // +build ios
168 // +build !x509omitbundledroots
169
170 package x509
171
172 func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
173 return nil, nil
174 }
175
176 func loadSystemRoots() (*CertPool, error) {
177 p := NewCertPool()
178 p.AppendCertsFromPEM([]byte(systemRootsPEM))
179 return p, nil
180 }
181 `
182
View as plain text