diff options
-rw-r--r-- | client/client.go | 5 | ||||
-rw-r--r-- | instance.go | 5 | ||||
-rw-r--r-- | x509.go | 130 | ||||
-rw-r--r-- | x509util/x509util.go | 134 |
4 files changed, 143 insertions, 131 deletions
diff --git a/client/client.go b/client/client.go index 54f75de..a95fc77 100644 --- a/client/client.go +++ b/client/client.go @@ -17,6 +17,7 @@ import ( "github.com/google/trillian/merkle/rfc6962" "github.com/system-transparency/stfe" "github.com/system-transparency/stfe/server/descriptor" + "github.com/system-transparency/stfe/x509util" "golang.org/x/net/context/ctxhttp" ) @@ -44,12 +45,12 @@ func NewClient(log *descriptor.Log, client *http.Client, useHttp bool, chain []* // client, namely, a pem-encoded certificate chain, a pem-encoded ed25519 // private key, and a json-encoded list of log operators (see descriptor). func NewClientFromPath(logId, chainPath, keyPath, operatorsPath string, cli *http.Client, useHttp bool) (*Client, error) { - c, err := stfe.LoadChain(chainPath) + c, err := x509util.LoadChain(chainPath) if err != nil { return nil, err } - k, err := stfe.LoadEd25519SigningKey(keyPath) + k, err := x509util.LoadEd25519SigningKey(keyPath) if err != nil && keyPath != "" { return nil, err } diff --git a/instance.go b/instance.go index 8e66f8f..baff329 100644 --- a/instance.go +++ b/instance.go @@ -12,6 +12,7 @@ import ( "github.com/golang/glog" "github.com/google/trillian" + "github.com/system-transparency/stfe/x509util" ) // Instance is an instance of a particular log front-end @@ -61,12 +62,12 @@ func NewInstance(lp *LogParameters, client trillian.TrillianLogClient, deadline // NewLogParameters initializes log parameters, assuming ed25519 signatures. func NewLogParameters(treeId int64, prefix string, anchorPath, keyPath string, maxRange, maxChain int64) (*LogParameters, error) { - anchorList, anchorPool, err := LoadTrustAnchors(anchorPath) + anchorList, anchorPool, err := x509util.LoadTrustAnchors(anchorPath) if err != nil { return nil, err } - key, err := LoadEd25519SigningKey(keyPath) + key, err := x509util.LoadEd25519SigningKey(keyPath) if err != nil { return nil, err } @@ -5,139 +5,15 @@ import ( "time" "crypto" - "crypto/ed25519" "crypto/rand" "crypto/tls" "crypto/x509" - "encoding/pem" - "io/ioutil" -) - -// LoadTrustAnchors loads a list of PEM-encoded certificates from file -func LoadTrustAnchors(path string) ([]*x509.Certificate, *x509.CertPool, error) { - rest, err := ioutil.ReadFile(path) - if err != nil { - return nil, nil, fmt.Errorf("failed reading trust anchors: %v", err) - } - - pool := x509.NewCertPool() - var anchors []*x509.Certificate - for len(rest) > 0 { - var block *pem.Block - block, rest = pem.Decode(rest) - if block == nil { - break - } - if block.Type != "CERTIFICATE" { - return nil, nil, fmt.Errorf("unexpected PEM block type: %s", block.Type) - } - - certificate, err := x509.ParseCertificate(block.Bytes) - if err != nil { - return nil, nil, fmt.Errorf("invalid trust anchor before rest(%s): %v", rest, err) - } - anchors = append(anchors, certificate) - pool.AddCert(certificate) - } - - if len(anchors) == 0 { - return nil, nil, fmt.Errorf("found no valid trust anchor in: %s", path) - } - return anchors, pool, nil -} - -// LoadEd25519SigningKey loads an Ed25519 private key from a given path -func LoadEd25519SigningKey(path string) (ed25519.PrivateKey, error) { - data, err := ioutil.ReadFile(path) - if err != nil { - return nil, fmt.Errorf("failed reading private key: %v", err) - } - return ParseEd25519PrivateKey(data) -} - -// ParseEd25519PrivateKey parses a PEM-encoded private key block -func ParseEd25519PrivateKey(data []byte) (ed25519.PrivateKey, error) { - block, rest := pem.Decode(data) - if block == nil { - return nil, fmt.Errorf("pem block: is empty") - } - if block.Type != "PRIVATE KEY" { - return nil, fmt.Errorf("bad pem block type: %v", block.Type) - } - if len(rest) != 0 { - return nil, fmt.Errorf("pem block: trailing data") - } - - key, err := x509.ParsePKCS8PrivateKey(block.Bytes) - if err != nil { - fmt.Errorf("x509 parser failed: %v", err) - } - switch t := key.(type) { - case ed25519.PrivateKey: - return key.(ed25519.PrivateKey), nil - default: - return nil, fmt.Errorf("unexpected signing key type: %v", t) - } -} - -// LoadChain loads a PEM-encoded certificate chain from a given path -func LoadChain(path string) ([]*x509.Certificate, error) { - blob, err := ioutil.ReadFile(path) - if err != nil { - return nil, fmt.Errorf("failed reading certificate chain: %v", err) - } - return ParseChain(blob) -} - -// ParseChain parses a PEM-encoded certificate chain -func ParseChain(rest []byte) ([]*x509.Certificate, error) { - var chain []*x509.Certificate - for len(rest) > 0 { - var block *pem.Block - block, rest = pem.Decode(rest) - if block == nil { - break - } - if block.Type != "CERTIFICATE" { - return nil, fmt.Errorf("unexpected pem block type: %v", block.Type) - } - - certificate, err := x509.ParseCertificate(block.Bytes) - if err != nil { - return nil, fmt.Errorf("failed parsing x509 certificate: %v", err) - } - chain = append(chain, certificate) - } - return chain, nil -} - -// ParseDerChain parses a list of base64 DER-encoded X.509 certificates, such -// that the first (zero-index) string is interpretted as an end-entity -// certificate and the remaining ones as the an intermediate CertPool. -func ParseDerChain(chain [][]byte) (*x509.Certificate, *x509.CertPool, error) { - var certificate *x509.Certificate - intermediatePool := x509.NewCertPool() - for index, der := range chain { - c, err := x509.ParseCertificate(der) - if err != nil { - return nil, nil, fmt.Errorf("certificate decoding failed: %v", err) - } - - if index == 0 { - certificate = c - } else { - intermediatePool.AddCert(c) - } - } - if certificate == nil { - return nil, nil, fmt.Errorf("certificate chain is empty") - } - return certificate, intermediatePool, nil -} + "github.com/system-transparency/stfe/x509util" +) func (lp *LogParameters) buildChainFromDerList(derChain [][]byte) ([]*x509.Certificate, error) { - certificate, intermediatePool, err := ParseDerChain(derChain) + certificate, intermediatePool, err := x509util.ParseDerChain(derChain) if err != nil { return nil, err } diff --git a/x509util/x509util.go b/x509util/x509util.go new file mode 100644 index 0000000..b33b4e9 --- /dev/null +++ b/x509util/x509util.go @@ -0,0 +1,134 @@ +package x509util + +import ( + "fmt" + + "crypto/ed25519" + "crypto/x509" + "encoding/pem" + "io/ioutil" +) + +// LoadTrustAnchors loads a list of PEM-encoded certificates from file +func LoadTrustAnchors(path string) ([]*x509.Certificate, *x509.CertPool, error) { + rest, err := ioutil.ReadFile(path) + if err != nil { + return nil, nil, fmt.Errorf("failed reading trust anchors: %v", err) + } + + pool := x509.NewCertPool() + var anchors []*x509.Certificate + for len(rest) > 0 { + var block *pem.Block + block, rest = pem.Decode(rest) + if block == nil { + break + } + if block.Type != "CERTIFICATE" { + return nil, nil, fmt.Errorf("unexpected PEM block type: %s", block.Type) + } + + certificate, err := x509.ParseCertificate(block.Bytes) + if err != nil { + return nil, nil, fmt.Errorf("invalid trust anchor before rest(%s): %v", rest, err) + } + + anchors = append(anchors, certificate) + pool.AddCert(certificate) + } + + if len(anchors) == 0 { + return nil, nil, fmt.Errorf("found no valid trust anchor in: %s", path) + } + return anchors, pool, nil +} + +// LoadEd25519SigningKey loads an Ed25519 private key from a given path +func LoadEd25519SigningKey(path string) (ed25519.PrivateKey, error) { + data, err := ioutil.ReadFile(path) + if err != nil { + return nil, fmt.Errorf("failed reading private key: %v", err) + } + return ParseEd25519PrivateKey(data) +} + +// ParseEd25519PrivateKey parses a PEM-encoded private key block +func ParseEd25519PrivateKey(data []byte) (ed25519.PrivateKey, error) { + block, rest := pem.Decode(data) + if block == nil { + return nil, fmt.Errorf("pem block: is empty") + } + if block.Type != "PRIVATE KEY" { + return nil, fmt.Errorf("bad pem block type: %v", block.Type) + } + if len(rest) != 0 { + return nil, fmt.Errorf("pem block: trailing data") + } + + key, err := x509.ParsePKCS8PrivateKey(block.Bytes) + if err != nil { + fmt.Errorf("x509 parser failed: %v", err) + } + switch t := key.(type) { + case ed25519.PrivateKey: + return key.(ed25519.PrivateKey), nil + default: + return nil, fmt.Errorf("unexpected signing key type: %v", t) + } +} + +// LoadChain loads a PEM-encoded certificate chain from a given path +func LoadChain(path string) ([]*x509.Certificate, error) { + blob, err := ioutil.ReadFile(path) + if err != nil { + return nil, fmt.Errorf("failed reading certificate chain: %v", err) + } + return ParseChain(blob) +} + +// ParseChain parses a PEM-encoded certificate chain +func ParseChain(rest []byte) ([]*x509.Certificate, error) { + var chain []*x509.Certificate + for len(rest) > 0 { + var block *pem.Block + block, rest = pem.Decode(rest) + if block == nil { + break + } + if block.Type != "CERTIFICATE" { + return nil, fmt.Errorf("unexpected pem block type: %v", block.Type) + } + + certificate, err := x509.ParseCertificate(block.Bytes) + if err != nil { + return nil, fmt.Errorf("failed parsing x509 certificate: %v", err) + } + chain = append(chain, certificate) + } + return chain, nil +} + +// ParseDerChain parses a list of base64 DER-encoded X.509 certificates, such +// that the first (zero-index) string is interpretted as an end-entity +// certificate and the remaining ones as the an intermediate CertPool. +func ParseDerChain(chain [][]byte) (*x509.Certificate, *x509.CertPool, error) { + var certificate *x509.Certificate + intermediatePool := x509.NewCertPool() + for index, der := range chain { + c, err := x509.ParseCertificate(der) + if err != nil { + return nil, nil, fmt.Errorf("certificate decoding failed: %v", err) + } + + if index == 0 { + certificate = c + } else { + intermediatePool.AddCert(c) + } + } + if certificate == nil { + return nil, nil, fmt.Errorf("certificate chain is empty") + } + return certificate, intermediatePool, nil +} + |