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 +} + | 
