aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--handler.go8
-rw-r--r--reqres.go56
-rw-r--r--type.go21
3 files changed, 64 insertions, 21 deletions
diff --git a/handler.go b/handler.go
index 42f9e23..e165a8f 100644
--- a/handler.go
+++ b/handler.go
@@ -50,16 +50,16 @@ func addEntry(ctx context.Context, i *instance, w http.ResponseWriter, r *http.R
return http.StatusBadRequest, err
} // request can be decoded
- leaf, err := VerifyAddEntryRequest(i.anchors, request)
+ leaf, appendix, err := VerifyAddEntryRequest(i.anchors, request)
if err != nil {
return http.StatusBadRequest, err
- } // leaf is valid, e.g., signed by a trust anchor
+ } // valid add-entry request
trillianRequest := trillian.QueueLeafRequest{
LogId: i.logID,
Leaf: &trillian.LogLeaf{
LeafValue: leaf,
- //TODO: add appendix here w/ chain + signature
+ ExtraData: appendix,
},
}
trillianResponse, err := i.client.QueueLeaf(ctx, &trillianRequest)
@@ -99,7 +99,7 @@ func getEntries(ctx context.Context, i *instance, w http.ResponseWriter, r *http
return http.StatusInternalServerError, fmt.Errorf("backend GetLeavesByRange returned unexpected leaf index: wanted %d, got %d", request.Start+int64(i), leaf.LeafIndex)
}
- glog.Infof("Entry(%d) => %v", request.Start+int64(i), leaf.GetLeafValue())
+ glog.Infof("Leaf(%d) => %v", request.Start+int64(i), leaf.GetLeafValue())
}
// TODO: use the returned root for tree_size santity checking against start?
diff --git a/reqres.go b/reqres.go
index 7bbb9e7..d8d88f2 100644
--- a/reqres.go
+++ b/reqres.go
@@ -39,7 +39,7 @@ type GetProofByHashRequest struct {
// GetEntryResponse is an assembled log entry and its associated appendix
type GetEntryResponse struct {
Leaf string `json:"leaf"` // base64-encoded StItem
- Signature string `json:"signature"` // base64-encoded DigitallySigned
+ Signature string `json:"signature"` // base64-encoded signature
Chain []string `json:"chain"` // base64-encoded X.509 certificates
}
@@ -122,18 +122,36 @@ func NewGetProofByHashRequest(httpRequest *http.Request) (GetProofByHashRequest,
}
// NewGetEntryResponse assembles a log entry and its appendix
-func NewGetEntryResponse(leaf []byte) GetEntryResponse {
+func NewGetEntryResponse(leaf, appendix []byte) (GetEntryResponse, error) {
+ var app Appendix
+ extra, err := tls.Unmarshal(appendix, &app)
+ if err != nil {
+ return GetEntryResponse{}, fmt.Errorf("failed tls unmarshaling appendix: %v (%v)", err, extra)
+ } else if len(extra) > 0 {
+ return GetEntryResponse{}, fmt.Errorf("tls umarshal found extra data for appendix: %v", extra)
+ }
+
+ chain := make([]string, 0, len(app.Chain))
+ for _, c := range app.Chain {
+ chain = append(chain, base64.StdEncoding.EncodeToString(c.Data))
+ }
+
return GetEntryResponse{
Leaf: base64.StdEncoding.EncodeToString(leaf),
- // TODO: add signature and chain
- }
+ Signature: base64.StdEncoding.EncodeToString(app.Signature),
+ Chain: chain,
+ }, nil
}
// NewGetEntriesResponse assembles a get-entries response
func NewGetEntriesResponse(leaves []*trillian.LogLeaf) (GetEntriesResponse, error) {
entries := make([]GetEntryResponse, 0, len(leaves))
for _, leaf := range leaves {
- entries = append(entries, NewGetEntryResponse(leaf.GetLeafValue())) // TODO: add signature and chain
+ entry, err := NewGetEntryResponse(leaf.GetLeafValue(), leaf.GetExtraData())
+ if err != nil {
+ return GetEntriesResponse{}, err
+ }
+ entries = append(entries, entry)
}
return GetEntriesResponse{entries}, nil
}
@@ -159,33 +177,33 @@ func NewGetAnchorsResponse(anchors []*x509.Certificate) GetAnchorsResponse {
}
// VerifyAddEntryRequest determines whether a well-formed AddEntryRequest should
-// be inserted into the log. If so, the serialized leaf value is returned.
-func VerifyAddEntryRequest(anchors ctfe.CertValidationOpts, r AddEntryRequest) ([]byte, error) {
+// be inserted into the log. The corresponding leaf and appendix is returned.
+func VerifyAddEntryRequest(anchors ctfe.CertValidationOpts, r AddEntryRequest) ([]byte, []byte, error) {
item, err := StItemFromB64(r.Item)
if err != nil {
- fmt.Errorf("failed decoding StItem: %v", err)
+ return nil, nil, fmt.Errorf("failed decoding StItem: %v", err)
}
leaf, err := tls.Marshal(item)
if err != nil {
- return nil, fmt.Errorf("failed tls marshaling StItem: %v", err)
+ return nil, nil, fmt.Errorf("failed tls marshaling StItem: %v", err)
}
certificate, err := base64.StdEncoding.DecodeString(r.Certificate)
if err != nil {
- return nil, fmt.Errorf("failed decoding certificate: %v", err)
+ return nil, nil, fmt.Errorf("failed decoding certificate: %v", err)
}
chain := make([][]byte, 0, 1)
chain = append(chain, certificate)
x509chain, err := ctfe.ValidateChain(chain, anchors)
if err != nil {
- return nil, fmt.Errorf("chain verification failed: %v", err)
+ return nil, nil, fmt.Errorf("chain verification failed: %v", err)
}
c := x509chain[0]
signature, err := base64.StdEncoding.DecodeString(r.Signature)
if err != nil {
- return nil, fmt.Errorf("failed decoding signature: %v", err)
+ return nil, nil, fmt.Errorf("failed decoding signature: %v", err)
}
var algo x509.SignatureAlgorithm
@@ -195,17 +213,21 @@ func VerifyAddEntryRequest(anchors ctfe.CertValidationOpts, r AddEntryRequest) (
case *ecdsa.PublicKey:
algo = x509.ECDSAWithSHA256
default:
- return nil, fmt.Errorf("unsupported public key algorithm: %v", t)
+ return nil, nil, fmt.Errorf("unsupported public key algorithm: %v", t)
}
if err := c.CheckSignature(algo, leaf, signature); err != nil {
- return nil, fmt.Errorf("invalid signature: %v", err)
+ return nil, nil, fmt.Errorf("invalid signature: %v", err)
}
-
// TODO: update doc of what signature "is", i.e., w/e x509 does
// TODO: doc in markdown/api.md what signature schemes we expect
- // TODO: return sig + chain
- return leaf, nil
+
+ appendix, err := tls.Marshal(NewAppendix(x509chain, signature))
+ if err != nil {
+ return nil, nil, fmt.Errorf("failed tls marshaling appendix: %v", err)
+ }
+
+ return leaf, appendix, nil
}
// UnpackJsonPost unpacks a json-encoded HTTP POST request into `unpack`
diff --git a/type.go b/type.go
index 9166209..f691f34 100644
--- a/type.go
+++ b/type.go
@@ -6,6 +6,7 @@ import (
"encoding/base64"
"github.com/google/certificate-transparency-go/tls"
+ "github.com/google/certificate-transparency-go/x509"
"github.com/google/trillian"
)
@@ -136,3 +137,23 @@ func StItemFromB64(s string) (StItem, error) {
}
return item, nil
}
+
+// Appendix is extra data that Trillian can store about a leaf
+type Appendix struct {
+ Signature []byte `tls:"minlen:0,maxlen:16383"`
+ Chain []RawCertificate `tls:"minlen:0,maxlen:65535"`
+}
+
+// RawCertificate is a serialized X.509 certificate
+type RawCertificate struct {
+ Data []byte `tls:"minlen:0,maxlen:65535"`
+}
+
+// NewAppendix creates a new leaf Appendix for an X.509 chain and signature
+func NewAppendix(x509Chain []*x509.Certificate, signature []byte) Appendix {
+ chain := make([]RawCertificate, 0, 2) // TODO: base length on config param
+ for _, c := range x509Chain {
+ chain = append(chain, RawCertificate{ c.Raw })
+ }
+ return Appendix{ Signature: signature, Chain: chain }
+}