From 7c5a0789ba80f890c868e81b981315dd53e9dd94 Mon Sep 17 00:00:00 2001 From: Linus Nordberg Date: Tue, 29 Apr 2014 16:56:09 +0200 Subject: Turn it all into an application. Warning: Rough edges. --- Emakefile | 3 +++ README | 13 ++++++++++ ebin/plop.app | 9 +++++++ include/plop.hrl | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/db.erl | 1 + src/plop.erl | 4 +-- src/plop.hrl | 79 -------------------------------------------------------- src/plop_app.erl | 9 +++++++ src/plop_sup.erl | 28 ++++++++++++++++++++ 9 files changed, 144 insertions(+), 81 deletions(-) create mode 100644 Emakefile create mode 100644 ebin/plop.app create mode 100644 include/plop.hrl delete mode 100644 src/plop.hrl create mode 100644 src/plop_app.erl create mode 100644 src/plop_sup.erl diff --git a/Emakefile b/Emakefile new file mode 100644 index 0000000..8869cf4 --- /dev/null +++ b/Emakefile @@ -0,0 +1,3 @@ +%% erl -make (-*- erlang -*-) +{"src/*", [debug_info, {i, "include/"}, {outdir, "ebin/"}]}. +{"test/*", [debug_info, {i, "include/"}, {outdir, "ebin/"}]}. diff --git a/README b/README index 56b2680..4312da4 100644 --- a/README +++ b/README @@ -3,3 +3,16 @@ implementing Certificate Transparency (RFC 6962). The first implementation is in Erlang. The only interface supported initially is Erlang messages. + + +Compile the application + + $ erl -make + +Start the application locally + + $ erl -boot start_sasl -pa ebin -eval "application:start(plop)." -plop Keyfile "src/test/rsakey.pem" -plop Passphrase "sikrit" + +Test the application + + [FIXME] diff --git a/ebin/plop.app b/ebin/plop.app new file mode 100644 index 0000000..f8d5d2c --- /dev/null +++ b/ebin/plop.app @@ -0,0 +1,9 @@ +%%% Application resource file for plop (in -*- erlang -*- mode). +{application, plop, + [{description, "The plop store"}, + {vsn, "0.0.1"}, + {modules, [plop_app, plop_sup, plop, db, ht, hex]}, + {applications, [kernel, stdlib]}, % crypto, public_key, mnesia + {registered, [plop, db]}, + {mod, {plop_app, []}} % <-- key file and pass phrase + ]}. diff --git a/include/plop.hrl b/include/plop.hrl new file mode 100644 index 0000000..5492024 --- /dev/null +++ b/include/plop.hrl @@ -0,0 +1,79 @@ +%%% plop data structures. Heavily based on RFC 6962. Some are for +%%% database storage, some for interfacing with consumers and some are +%%% for serialisation. + +-type signature_type() :: certificate_timestamp | tree_hash | test. % uint8 +-type entry_type() :: x509 | precert | test. % uint16 +-type leaf_type() :: timestamped_entry | test. % uint8 + +%% @doc What's stored in the database. +-record(plop, { + index :: non_neg_integer(), % Primary key. + hash :: binary(), % SHA-256 over #FIXME.entry. Indexed in db. + spt :: binary() % serialise(#spt_on_wire{}) + }). + +%% @doc Merkle Tree Leaf -- input to hash function for leaf hashes. +-record(mtl, { + version = 1 :: pos_integer(), + leaf_type = timestamped_entry :: leaf_type(), + entry :: timestamped_entry() + }). +-type mtl() :: #mtl{}. + +%% @doc Parts of what goes in an SPT. Used for FIXME. +%% -record(spt, { +%% version = 1 :: pos_integer(), +%% signature_type :: signature_type(), +%% entry :: timestamped_entry() +%% }). +%%-type spt() :: #spt{}. + +-record(spt_on_wire, { + version :: pos_integer(), % uint8 + logid :: binary(), % SHA-256 over DER encoded public log key + timestamp :: integer(), % uint64 + signature :: binary() + }). +-type spt_on_wire() :: #spt_on_wire{}. + +%% @doc What's signed in an SPT. Used for serialisation before hasning +%% and signing. FIXME: Overlapping #spt{} -- merge somehow. +-record(spt_signed, { + version :: pos_integer(), + signature_type :: signature_type(), + timestamp :: integer(), + entry_type :: entry_type(), + signed_entry :: binary() + }). +-type spt_signed() :: #spt_signed{}. + +%% Internal representation of a data entry. +-record(timestamped_entry, { + timestamp = now :: now | integer(), + entry_type :: entry_type(), + entry :: binary() + }). +-type timestamped_entry() :: #timestamped_entry{}. + +%% %% Part of interface to plop:add/1. +%% -record(plop_entry, { +%% type :: entry_type(), +%% data :: binary() +%% }). +%% -type plop_entry() :: #plop_entry{}. + + +%% @doc The parts of an STH which is to be signed. Used as the +%% interface to plop:sth/1, for testing. Should probably be internal +%% to plop, if that can be arranged wrt testing. +-record(sth, { + version = 1 :: pos_integer(), + signature_type :: signature_type(), + timestamp = now :: 'now' | integer(), + tree_size :: integer(), + root_hash :: binary() % SHA-256 + }). +-type sth() :: #sth{}. + +-export_type([timestamped_entry/0, mtl/0, entry_type/0]). diff --git a/src/db.erl b/src/db.erl index e1604d1..ef9c536 100644 --- a/src/db.erl +++ b/src/db.erl @@ -64,6 +64,7 @@ code_change(_OldVsn, State, _Extra) -> {ok, State}. terminate(_Reason, _State) -> + io:format("~p terminating~n", [?MODULE]), ok. %%%%%%%%%%%%%%%%%%%% diff --git a/src/plop.erl b/src/plop.erl index bee9cb4..6ffc856 100644 --- a/src/plop.erl +++ b/src/plop.erl @@ -31,8 +31,7 @@ hashtree :: ht:head()}). start_link() -> - db:start_link(), - start_link("test/rsakey.pem", "sikrit"). + start_link("src/test/rsakey.pem", "sikrit"). % FIXME: Remove. start_link(Keyfile, Passphrase) -> gen_server:start_link({local, ?MODULE}, ?MODULE, [Keyfile, Passphrase], []). @@ -59,6 +58,7 @@ code_change(_OldVsn, State, _Extra) -> {ok, State}. terminate(_Reason, _State) -> + io:format("~p terminating~n", [?MODULE]), ok. %%%%%%%%%%%%%%%%%%%% diff --git a/src/plop.hrl b/src/plop.hrl deleted file mode 100644 index 5492024..0000000 --- a/src/plop.hrl +++ /dev/null @@ -1,79 +0,0 @@ -%%% plop data structures. Heavily based on RFC 6962. Some are for -%%% database storage, some for interfacing with consumers and some are -%%% for serialisation. - --type signature_type() :: certificate_timestamp | tree_hash | test. % uint8 --type entry_type() :: x509 | precert | test. % uint16 --type leaf_type() :: timestamped_entry | test. % uint8 - -%% @doc What's stored in the database. --record(plop, { - index :: non_neg_integer(), % Primary key. - hash :: binary(), % SHA-256 over #FIXME.entry. Indexed in db. - spt :: binary() % serialise(#spt_on_wire{}) - }). - -%% @doc Merkle Tree Leaf -- input to hash function for leaf hashes. --record(mtl, { - version = 1 :: pos_integer(), - leaf_type = timestamped_entry :: leaf_type(), - entry :: timestamped_entry() - }). --type mtl() :: #mtl{}. - -%% @doc Parts of what goes in an SPT. Used for FIXME. -%% -record(spt, { -%% version = 1 :: pos_integer(), -%% signature_type :: signature_type(), -%% entry :: timestamped_entry() -%% }). -%%-type spt() :: #spt{}. - --record(spt_on_wire, { - version :: pos_integer(), % uint8 - logid :: binary(), % SHA-256 over DER encoded public log key - timestamp :: integer(), % uint64 - signature :: binary() - }). --type spt_on_wire() :: #spt_on_wire{}. - -%% @doc What's signed in an SPT. Used for serialisation before hasning -%% and signing. FIXME: Overlapping #spt{} -- merge somehow. --record(spt_signed, { - version :: pos_integer(), - signature_type :: signature_type(), - timestamp :: integer(), - entry_type :: entry_type(), - signed_entry :: binary() - }). --type spt_signed() :: #spt_signed{}. - -%% Internal representation of a data entry. --record(timestamped_entry, { - timestamp = now :: now | integer(), - entry_type :: entry_type(), - entry :: binary() - }). --type timestamped_entry() :: #timestamped_entry{}. - -%% %% Part of interface to plop:add/1. -%% -record(plop_entry, { -%% type :: entry_type(), -%% data :: binary() -%% }). -%% -type plop_entry() :: #plop_entry{}. - - -%% @doc The parts of an STH which is to be signed. Used as the -%% interface to plop:sth/1, for testing. Should probably be internal -%% to plop, if that can be arranged wrt testing. --record(sth, { - version = 1 :: pos_integer(), - signature_type :: signature_type(), - timestamp = now :: 'now' | integer(), - tree_size :: integer(), - root_hash :: binary() % SHA-256 - }). --type sth() :: #sth{}. - --export_type([timestamped_entry/0, mtl/0, entry_type/0]). diff --git a/src/plop_app.erl b/src/plop_app.erl new file mode 100644 index 0000000..d2e99ac --- /dev/null +++ b/src/plop_app.erl @@ -0,0 +1,9 @@ +-module(plop_app). +-behaviour(application). +-export([start/2, stop/1]). + +start(_Type, Args) -> + plop_sup:start_link(Args). + +stop(_State) -> + ok. diff --git a/src/plop_sup.erl b/src/plop_sup.erl new file mode 100644 index 0000000..18ed926 --- /dev/null +++ b/src/plop_sup.erl @@ -0,0 +1,28 @@ +-module(plop_sup). +-behaviour(supervisor). + +-export([start_link/1, init/1]). +-export([start_in_shell/0]). + +start_link(Args) -> + supervisor:start_link({local, ?MODULE}, ?MODULE, Args). + +%% For testing. +start_in_shell() -> + {ok, Pid} = start_link([]), + unlink(Pid). + +%% Supervisor callback +init(_Args) -> + {ok, {{one_for_one, 3, 10}, + [{the_plop, + {plop, start_link, []}, % Here's where key file name and pass phrase go. + permanent, + 10000, % Shut down in 10s. + worker, [plop]}, + {the_db, + {db, start_link, []}, + permanent, + 10000, + worker, [db]} + ]}}. -- cgit v1.1