diff options
Diffstat (limited to 'src/catlfish.erl')
-rw-r--r-- | src/catlfish.erl | 117 |
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)]. |