summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/catlfish.erl117
1 files changed, 60 insertions, 57 deletions
diff --git a/src/catlfish.erl b/src/catlfish.erl
index e48f788..d483249 100644
--- a/src/catlfish.erl
+++ b/src/catlfish.erl
@@ -124,20 +124,7 @@ add_to_db(Type, LeafCert, CertChain, EntryHash) ->
leaf_type = timestamped_entry,
entry = TSE}),
MTLHash = ht:leaf_hash(MTLText),
- ExtraData =
- case Type of
- normal -> CertChain;
- precert -> [LeafCert | CertChain]
- end,
- LogEntry =
- list_to_binary(
- [encode_tls_vector(MTLText, 4),
- encode_tls_vector(
- encode_tls_vector(
- list_to_binary(
- [encode_tls_vector(C, 3) || C <- ExtraData]),
- 3),
- 4)]),
+ LogEntry = pack_entry(Type, MTLText, LeafCert, CertChain),
ok = plop:add(LogEntry, MTLHash, EntryHash),
{TSE, MTLHash}.
@@ -157,7 +144,7 @@ add_chain(LeafCert, CertChain, Type) ->
exit({internalerror, "Rate limiting"})
end;
{_Index, MTLHash, DBEntry} ->
- {MTLText, _ExtraData} = unpack_entry(DBEntry),
+ {_Type, MTLText, _Cert, _Chain} = unpack_entry(DBEntry),
MTL = deserialise_mtl(MTLText),
MTLText = serialise(MTL), % verify FIXME: remove
{MTL#mtl.entry, MTLHash}
@@ -236,8 +223,9 @@ entries(Start, End) ->
entry_and_proof(Index, TreeSize) ->
case plop:inclusion_and_entry(Index, TreeSize) of
{ok, Entry, Path} ->
- {MTL, ExtraData} = unpack_entry(Entry),
- {[{leaf_input, base64:encode(MTL)},
+ {Type, MTLText, Cert, Chain} = unpack_entry(Entry),
+ ExtraData = extra_data(Type, Cert, Chain),
+ {[{leaf_input, base64:encode(MTLText)},
{extra_data, base64:encode(ExtraData)},
{audit_path, [base64:encode(X) || X <- Path]}]};
{notfound, Msg} ->
@@ -253,29 +241,6 @@ init_cache_table() ->
end,
ets:new(?CACHE_TABLE, [set, public, named_table]).
-deserialise_extra_data(<<>>) ->
- [];
-deserialise_extra_data(ExtraData) ->
- {E, Rest} = decode_tls_vector(ExtraData, 3),
- [E | deserialise_extra_data(Rest)].
-
-chain_from_mtl_extradata(MTL, ExtraData) ->
- TimestampedEntry = MTL#mtl.entry,
- Chain = deserialise_extra_data(ExtraData),
- case TimestampedEntry#timestamped_entry.entry_type of
- x509_entry ->
- SignedEntry = TimestampedEntry#timestamped_entry.signed_entry,
- [SignedEntry#signed_x509_entry.asn1_cert | Chain];
- precert_entry ->
- Chain
- end.
-
-mtl_and_extra_from_entry(Entry) ->
- {MTLText, ExtraDataPacked} = unpack_entry(Entry),
- {ExtraData, <<>>} = decode_tls_vector(ExtraDataPacked, 3),
- MTL = deserialise_mtl(MTLText),
- {MTL, ExtraData}.
-
verify_mtl(MTL, LeafCert, CertChain) ->
Timestamp = MTL#mtl.entry#timestamped_entry.timestamp,
EntryType = MTL#mtl.entry#timestamped_entry.entry_type,
@@ -293,15 +258,14 @@ verify_entry(Entry) ->
RootCerts = known_roots(),
verify_entry(Entry, RootCerts).
-verify_entry(Entry, RootCerts) ->
- {MTL, ExtraData} = mtl_and_extra_from_entry(Entry),
- Chain = chain_from_mtl_extradata(MTL, ExtraData),
-
- case x509:normalise_chain(RootCerts, Chain) of
- {ok, [LeafCert|CertChain]} ->
- case verify_mtl(MTL, LeafCert, CertChain) of
+%% Used from plop.
+verify_entry(PackedEntry, RootCerts) ->
+ {_Type, MTLText, Cert, Chain} = unpack_entry(PackedEntry),
+ case x509:normalise_chain(RootCerts, [Cert | Chain]) of
+ {ok, [Cert | FullChain]} ->
+ case verify_mtl(deserialise_mtl(MTLText), Cert, FullChain) of
ok ->
- {ok, ht:leaf_hash(serialise(MTL))};
+ {ok, ht:leaf_hash(MTLText)};
error ->
{error, "MTL verification failed"}
end;
@@ -309,24 +273,63 @@ verify_entry(Entry, RootCerts) ->
{error, Reason}
end.
-entryhash_from_entry(Entry) ->
- {MTL, ExtraData} = mtl_and_extra_from_entry(Entry),
- Chain = chain_from_mtl_extradata(MTL, ExtraData),
- crypto:hash(sha256, Chain).
+%% Used from plop.
+entryhash_from_entry(PackedEntry) ->
+ {_Type, _MTLText, Cert, Chain} = unpack_entry(PackedEntry),
+ crypto:hash(sha256, [Cert | Chain]).
%% Private functions.
--spec unpack_entry(binary()) -> {binary(), binary()}.
+-spec pack_entry(normal|precert, binary(), binary(), [binary()]) -> binary().
+pack_entry(Type, MTLText, EndEntityCert, CertChain) ->
+ list_to_binary(
+ [tlv:encode(<<"MTL1">>, MTLText),
+ tlv:encode(case Type of
+ normal -> <<"EEC1">>;
+ precert -> <<"PRC1">>
+ end, EndEntityCert),
+ tlv:encode(<<"CHN1">>,
+ list_to_binary(
+ [tlv:encode(<<"X509">>, E) || E <- CertChain]))]).
+
+-spec unpack_entry(binary()) -> {normal|precert, binary(), binary(), [binary()]}.
unpack_entry(Entry) ->
- {MTL, Rest} = decode_tls_vector(Entry, 4),
- {ExtraData, <<>>} = decode_tls_vector(Rest, 4),
- {MTL, ExtraData}.
+ {<<"MTL1">>, MTLText, Rest1} = tlv:decode(Entry),
+ {EECType, EndEntityCert, Rest2} = tlv:decode(Rest1),
+ Type = case EECType of
+ <<"EEC1">> ->
+ normal;
+ <<"PRC1">> ->
+ precert
+ end,
+ {<<"CHN1">>, PackedChain, _Rest3} = tlv:decode(Rest2), % Ignore rest.
+ Chain = unpack_certchain(PackedChain),
+ {Type, MTLText, EndEntityCert, Chain}.
+
+unpack_certchain(<<>>) ->
+ [];
+unpack_certchain(Data) ->
+ {<<"X509">>, Unpacked, Rest} = tlv:decode(Data),
+ [Unpacked | unpack_certchain(Rest)].
+
+extra_data(Type, Cert, Chain) ->
+ EncodedChain = encode_tls_vector(
+ list_to_binary(
+ [encode_tls_vector(C, 3) || C <- Chain]), 3),
+ case Type of
+ normal ->
+ EncodedChain;
+ precert ->
+ list_to_binary(
+ [encode_tls_vector(Cert, 3) | EncodedChain])
+ end.
-spec x_entries([{non_neg_integer(), binary(), binary()}]) -> list().
x_entries([]) ->
[];
x_entries([H|T]) ->
{_Index, _Hash, Entry} = H,
- {MTL, ExtraData} = unpack_entry(Entry),
+ {Type, MTL, Cert, Chain} = unpack_entry(Entry),
+ ExtraData = extra_data(Type, Cert, Chain),
[{[{leaf_input, base64:encode(MTL)},
{extra_data, base64:encode(ExtraData)}]} | x_entries(T)].