aboutsummaryrefslogtreecommitdiff
path: root/crypto.go
diff options
context:
space:
mode:
authorRasmus Dahlberg <rasmus.dahlberg@kau.se>2020-11-05 12:38:13 +0100
committerRasmus Dahlberg <rasmus.dahlberg@kau.se>2020-11-05 12:38:13 +0100
commit7ba39431438ea37504f4901e50e1ff3fd4ca9939 (patch)
tree8f23a45dc4bf8fccdbb939f1671cf687c58b4254 /crypto.go
parent906f3161dbbff07515244134e0e88641dd68fbb3 (diff)
renamed verify.go to crypto.go
Chains and signatures are verified here, but signatures are also produced.
Diffstat (limited to 'crypto.go')
-rw-r--r--crypto.go81
1 files changed, 81 insertions, 0 deletions
diff --git a/crypto.go b/crypto.go
new file mode 100644
index 0000000..47c16bb
--- /dev/null
+++ b/crypto.go
@@ -0,0 +1,81 @@
+package stfe
+
+import (
+ "fmt"
+ "time"
+
+ "crypto"
+ "crypto/rand"
+ "crypto/tls"
+ "crypto/x509"
+
+ "github.com/system-transparency/stfe/x509util"
+)
+
+// buildChainFromDerList builds an X.509 certificate chain from a list of
+// DER-encoded certificates using the log's configured trust anchors, extended
+// key-usages, and maximum chain length (which includes the trust anchor).
+func (lp *LogParameters) buildChainFromDerList(derChain [][]byte) ([]*x509.Certificate, error) {
+ certificate, intermediatePool, err := x509util.ParseDerChain(derChain)
+ if err != nil {
+ return nil, err
+ }
+ opts := x509.VerifyOptions{
+ Roots: lp.AnchorPool,
+ Intermediates: intermediatePool,
+ KeyUsages: lp.KeyUsage, // no extended key usage passes by default
+ }
+
+ chains, err := certificate.Verify(opts)
+ if err != nil {
+ return nil, fmt.Errorf("chain verification failed: %v", err)
+ }
+ if len(chains) == 0 {
+ return nil, fmt.Errorf("bad certificate chain length: empty")
+ }
+
+ // there might be several valid chains
+ for _, chain := range chains {
+ if int64(len(chain)) <= lp.MaxChain {
+ return chain, nil // just pick the first valid chain
+ }
+ }
+ return nil, fmt.Errorf("bad certificate chain length: too large")
+}
+
+// verifySignature checks if signature is valid for some serialized data. The
+// only supported signature scheme is ed25519(0x0807), see ยง4.2.3 in RFC 8446.
+func (lp *LogParameters) verifySignature(certificate *x509.Certificate, scheme tls.SignatureScheme, serialized, signature []byte) error {
+ if scheme != tls.Ed25519 {
+ return fmt.Errorf("unsupported signature scheme: %v", scheme)
+ }
+ if err := certificate.CheckSignature(x509.PureEd25519, serialized, signature); err != nil {
+ return fmt.Errorf("invalid signature: %v", err)
+ }
+ return nil
+}
+
+// genV1Sdi issues a new SignedDebugInfoV1 StItem from a serialized leaf value
+func (lp *LogParameters) genV1Sdi(serialized []byte) (*StItem, error) {
+ sig, err := lp.Signer.Sign(rand.Reader, serialized, crypto.Hash(0)) // ed25519
+ if err != nil {
+ return nil, fmt.Errorf("ed25519 signature failed: %v", err)
+ }
+ lastSdiTimestamp.Set(float64(time.Now().Unix()), lp.id())
+ return NewSignedDebugInfoV1(lp.LogId, []byte("reserved"), sig), nil
+}
+
+// genV1Sth issues a new SignedTreeHeadV1 StItem from a TreeHeadV1 structure
+func (lp *LogParameters) genV1Sth(th *TreeHeadV1) (*StItem, error) {
+ serialized, err := th.Marshal()
+ if err != nil {
+ return nil, fmt.Errorf("failed tls marshaling tree head: %v", err)
+ }
+ sig, err := lp.Signer.Sign(rand.Reader, serialized, crypto.Hash(0)) // ed25519
+ if err != nil {
+ return nil, fmt.Errorf("ed25519 signature failed: %v", err)
+ }
+ lastSthTimestamp.Set(float64(time.Now().Unix()), lp.id())
+ lastSthSize.Set(float64(th.TreeSize), lp.id())
+ return NewSignedTreeHeadV1(th, lp.LogId, sig), nil
+}