diff options
author | Magnus Ahltorp <map@kth.se> | 2017-02-17 23:31:02 +0100 |
---|---|---|
committer | Magnus Ahltorp <map@kth.se> | 2017-02-17 23:31:02 +0100 |
commit | 88a9c02a19a9dabc375a40da8c8ed36c44807b65 (patch) | |
tree | 61a8c34bd16bf06ef7561f1093a2f0fe68d9634c | |
parent | 320e7346ab80feb58a75703e2fa79fb31887394d (diff) |
Support requirement that storage servers sign stored entries
Make SCT cache mandatory.
The signature server now requires signatures from the storage nodes,
so if SCT is not present in the cache, always send entries to
storage servers to collect signatures. Also send SCT when committing
entry to storage servers.
-rw-r--r-- | src/catlfish.erl | 69 | ||||
-rwxr-xr-x | tools/compileconfig.py | 11 |
2 files changed, 50 insertions, 30 deletions
diff --git a/src/catlfish.erl b/src/catlfish.erl index 4bf1cdf..04b3332 100644 --- a/src/catlfish.erl +++ b/src/catlfish.erl @@ -5,7 +5,7 @@ -export([add_chain/3, entries/2, entry_and_proof/2]). -export([known_roots/0, update_known_roots/0]). -export([init_cache_table/0]). --export([entryhash_from_entry/1, verify_entry/1, verify_entry/2]). +-export([entryhash_from_entry/1, verify_entry/1, verify_entry/2, spt_data/1]). -include_lib("eunit/include/eunit.hrl"). -define(PROTOCOL_VERSION, 0). @@ -92,28 +92,22 @@ deserialise_entry_type(<<1:16>>) -> serialise_signature_type(certificate_timestamp) -> <<0:8>>. -calc_sct(TimestampedEntry) -> +spt_data(DBEntry) -> + {_Type, MTLText, _Cert, _Chain} = unpack_entry(DBEntry), + MTL = deserialise_mtl(MTLText), + TSE = MTL#mtl.entry, + sct_data(TSE). + +sct_data(TimestampedEntry) -> + list_to_binary([<<?PROTOCOL_VERSION:8>>, + serialise_signature_type(certificate_timestamp), + serialise(TimestampedEntry)]). + +calc_sct(TimestampedEntry, Signatures) -> plop:serialise( - plop:spt(list_to_binary([<<?PROTOCOL_VERSION:8>>, - serialise_signature_type(certificate_timestamp), - serialise(TimestampedEntry)]))). - -get_sct(Hash, TimestampedEntry) -> - case application:get_env(catlfish, sctcache_root_path) of - {ok, RootPath} -> - case perm:readfile(RootPath, Hash) of - Contents when is_binary(Contents) -> - Contents; - noentry -> - SCT = calc_sct(TimestampedEntry), - ok = perm:ensurefile_nosync(RootPath, Hash, SCT), - SCT - end; - _ -> - calc_sct(TimestampedEntry) - end. + plop:spt(sct_data(TimestampedEntry), Signatures)). -add_to_db(Type, LeafCert, CertChain, EntryHash) -> +create_logentry(Type, LeafCert, CertChain) -> EntryType = case Type of normal -> x509_entry; precert -> precert_entry @@ -125,21 +119,34 @@ add_to_db(Type, LeafCert, CertChain, EntryHash) -> entry = TSE}), MTLHash = ht:leaf_hash(MTLText), LogEntry = pack_entry(Type, MTLText, LeafCert, CertChain), - ok = plop:add(LogEntry, MTLHash, EntryHash), - {TSE, MTLHash}. + {TSE, MTLHash, LogEntry}. get_ratelimit_token(Type) -> ratelimit:get_token(Type). + +maybe_add_to_db(Hash, LogEntry, TimestampedEntry, HasEntry) -> + CachedSCTSig = plop:get_spt(Hash), + + case {HasEntry, CachedSCTSig} of + {true, SCT} when is_binary(SCT) -> + SCT; + _ -> + {ok, Signatures} = plop:add(LogEntry, Hash), + SCT = calc_sct(TimestampedEntry, Signatures), + plop:add_spt(Hash, SCT), + SCT + end. + -spec add_chain(binary(), [binary()], normal|precert) -> {[{_,_},...]}. add_chain(LeafCert, CertChain, Type) -> EntryHash = crypto:hash(sha256, [LeafCert | CertChain]), - {TimestampedEntry, Hash} = + {{TimestampedEntry, Hash, LogEntry}, HasEntry} = case plop:get(EntryHash) of notfound -> case get_ratelimit_token(add_chain) of ok -> - add_to_db(Type, LeafCert, CertChain, EntryHash); + {create_logentry(Type, LeafCert, CertChain), false}; _ -> exit({internalerror, "Rate limiting"}) end; @@ -147,10 +154,18 @@ add_chain(LeafCert, CertChain, Type) -> {_Type, MTLText, _Cert, _Chain} = unpack_entry(DBEntry), MTL = deserialise_mtl(MTLText), MTLText = serialise(MTL), % verify FIXME: remove - {MTL#mtl.entry, MTLHash} + {{MTL#mtl.entry, MTLHash, DBEntry}, true} end, - SCT_sig = get_sct(Hash, TimestampedEntry), + SCT_sig = maybe_add_to_db(Hash, LogEntry, TimestampedEntry, HasEntry), + + case HasEntry of + false -> + plop:commit(Hash, EntryHash, SCT_sig); + _ -> + none + end, + {[{sct_version, ?PROTOCOL_VERSION}, {id, base64:encode(plop:get_logid())}, {timestamp, TimestampedEntry#timestamped_entry.timestamp}, diff --git a/tools/compileconfig.py b/tools/compileconfig.py index fd77b90..9973a95 100755 --- a/tools/compileconfig.py +++ b/tools/compileconfig.py @@ -257,8 +257,7 @@ def gen_config(nodename, config, localconfig): if nodetype & set(["frontendnodes", "mergenodes"]): catlfishconfig.append((Symbol("known_roots_path"), localconfig["paths"]["knownroots"])) if "frontendnodes" in nodetype: - if "sctcaching" in options: - catlfishconfig.append((Symbol("sctcache_root_path"), paths["db"] + "sctcache/")) + plopconfig.append((Symbol("sptcache_root_path"), paths["db"] + "sctcache")) if "ratelimits" in localconfig: ratelimits = map(parse_ratelimit, localconfig["ratelimits"].items()) catlfishconfig.append((Symbol("ratelimits"), ratelimits)) @@ -312,6 +311,8 @@ def gen_config(nodename, config, localconfig): (Symbol("sendsth_verified_path"), paths["db"] + "sendsth-verified"), (Symbol("entryhash_from_entry"), (Symbol("catlfish"), Symbol("entryhash_from_entry"))), + (Symbol("spt_data"), + (Symbol("catlfish"), Symbol("spt_data"))), ] if "storagenodes" in nodetype: plopconfig += [ @@ -340,12 +341,14 @@ def gen_config(nodename, config, localconfig): allowed_clients = [] allowed_servers = [] + storagenodenames = [node["name"] for node in config["storagenodes"]] services = set() + storage_sign_quorum = config.get("storage-sign-quorum-size", 0) if "frontendnodes" in nodetype: - storagenodenames = [node["name"] for node in config["storagenodes"]] reloadableplopconfig.append((Symbol("storage_nodes"), storagenodeaddresses)) reloadableplopconfig.append((Symbol("storage_nodes_quorum"), config["storage-quorum-size"])) + reloadableplopconfig.append((Symbol("storage_sign_quorum"), storage_sign_quorum)) services.add(Symbol("ht")) allowed_clients += allowed_clients_frontend(mergenodenames, primarymergenodename) allowed_clients += allowed_clients_public() @@ -353,6 +356,7 @@ def gen_config(nodename, config, localconfig): if "storagenodes" in nodetype: allowed_clients += allowed_clients_storage(frontendnodenames, mergenodenames) if "signingnodes" in nodetype: + reloadableplopconfig.append((Symbol("storage_sign_quorum"), storage_sign_quorum)) allowed_clients += allowed_clients_signing(frontendnodenames, primarymergenodename) services = [Symbol("sign")] if "mergenodes" in nodetype: @@ -409,6 +413,7 @@ def gen_config(nodename, config, localconfig): reloadableplopconfig += [ (Symbol("allowed_clients"), list(allowed_clients)), (Symbol("allowed_servers"), list(allowed_servers)), + (Symbol("storage_node_names"), list(storagenodenames)), (Symbol("apikeys"), apikeys), (Symbol("version"), config["version"]), ] |