mirror of https://github.com/golang/go.git
crypto/x509: embed certificates on darwin/arm
Change-Id: Ia6b06f19e5ac424f01a1b90b78b507363b0c4577 Reviewed-on: https://go-review.googlesource.com/5061 Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
This commit is contained in:
parent
2bcfe8b935
commit
b2c2bc4856
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build cgo
|
||||
// +build cgo,!arm
|
||||
|
||||
package x509
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:generate go run root_darwin_arm_gen.go -output root_darwin_arm.go
|
||||
|
||||
package x509
|
||||
|
||||
import "os/exec"
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,187 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// Generates root_darwin_arm.go.
|
||||
//
|
||||
// As of iOS 8, there is no API for querying the system trusted X.509 root
|
||||
// certificates. We could use SecTrustEvaluate to verify that a trust chain
|
||||
// exists for a certificate, but the x509 API requires returning the entire
|
||||
// chain.
|
||||
//
|
||||
// Apple publishes the list of trusted root certificates for iOS on
|
||||
// support.apple.com. So we parse the list and extract the certificates from
|
||||
// an OS X machine and embed them into the x509 package.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/format"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"math/big"
|
||||
"net/http"
|
||||
"os/exec"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var output = flag.String("output", "root_darwin_arm.go", "file name to write")
|
||||
|
||||
func main() {
|
||||
certs, err := selectCerts()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
fmt.Fprintf(buf, "// Created by root_darwin_arm_gen --output %s; DO NOT EDIT\n", *output)
|
||||
fmt.Fprintf(buf, "%s", header)
|
||||
|
||||
fmt.Fprintf(buf, "const systemRootsPEM = `\n")
|
||||
for _, cert := range certs {
|
||||
b := &pem.Block{
|
||||
Type: "CERTIFICATE",
|
||||
Bytes: cert.Raw,
|
||||
}
|
||||
if err := pem.Encode(buf, b); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(buf, "`")
|
||||
|
||||
source, err := format.Source(buf.Bytes())
|
||||
if err != nil {
|
||||
log.Fatal("source format error:", err)
|
||||
}
|
||||
if err := ioutil.WriteFile(*output, source, 0644); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func selectCerts() ([]*x509.Certificate, error) {
|
||||
ids, err := fetchCertIDs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
scerts, err := sysCerts()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var certs []*x509.Certificate
|
||||
for _, id := range ids {
|
||||
sn, ok := big.NewInt(0).SetString(id.serialNumber, 0) // 0x prefix selects hex
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid serial number: %q", id.serialNumber)
|
||||
}
|
||||
ski, ok := big.NewInt(0).SetString(id.subjectKeyID, 0)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid Subject Key ID: %q", id.subjectKeyID)
|
||||
}
|
||||
|
||||
for _, cert := range scerts {
|
||||
if sn.Cmp(cert.SerialNumber) != 0 {
|
||||
continue
|
||||
}
|
||||
cski := big.NewInt(0).SetBytes(cert.SubjectKeyId)
|
||||
if ski.Cmp(cski) != 0 {
|
||||
continue
|
||||
}
|
||||
certs = append(certs, cert)
|
||||
break
|
||||
}
|
||||
}
|
||||
return certs, nil
|
||||
}
|
||||
|
||||
func sysCerts() (certs []*x509.Certificate, err error) {
|
||||
cmd := exec.Command("/usr/bin/security", "find-certificate", "-a", "-p", "/System/Library/Keychains/SystemRootCertificates.keychain")
|
||||
data, err := cmd.Output()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for len(data) > 0 {
|
||||
var block *pem.Block
|
||||
block, data = pem.Decode(data)
|
||||
if block == nil {
|
||||
break
|
||||
}
|
||||
if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
cert, err := x509.ParseCertificate(block.Bytes)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
certs = append(certs, cert)
|
||||
}
|
||||
return certs, nil
|
||||
}
|
||||
|
||||
type certID struct {
|
||||
serialNumber string
|
||||
subjectKeyID string
|
||||
}
|
||||
|
||||
// fetchCertIDs fetches IDs of iOS X509 certificates from apple.com.
|
||||
func fetchCertIDs() ([]certID, error) {
|
||||
resp, err := http.Get("https://support.apple.com/en-us/HT204132")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
text := string(body)
|
||||
text = text[strings.Index(text, "<section id=trusted"):]
|
||||
text = text[:strings.Index(text, "</section>")]
|
||||
|
||||
lines := strings.Split(text, "\n")
|
||||
var ids []certID
|
||||
var id certID
|
||||
for i, ln := range lines {
|
||||
if i == len(lines)-1 {
|
||||
break
|
||||
}
|
||||
const sn = "Serial Number:"
|
||||
if ln == sn {
|
||||
id.serialNumber = "0x" + strings.Replace(strings.TrimSpace(lines[i+1]), ":", "", -1)
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(ln, sn) {
|
||||
// extract hex value from parentheses.
|
||||
id.serialNumber = ln[strings.Index(ln, "(")+1 : len(ln)-1]
|
||||
continue
|
||||
}
|
||||
if strings.TrimSpace(ln) == "X509v3 Subject Key Identifier:" {
|
||||
id.subjectKeyID = "0x" + strings.Replace(strings.TrimSpace(lines[i+1]), ":", "", -1)
|
||||
ids = append(ids, id)
|
||||
id = certID{}
|
||||
}
|
||||
}
|
||||
return ids, nil
|
||||
}
|
||||
|
||||
const header = `
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package x509
|
||||
|
||||
func initSystemRoots() {
|
||||
systemRoots = NewCertPool()
|
||||
systemRoots.AppendCertsFromPEM([]byte(systemRootsPEM))
|
||||
}
|
||||
`
|
||||
Loading…
Reference in New Issue